CachedBluetoothDevice.java revision 6e4060212e537bdcb69b21c2ba814c23cd393d42
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 69436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final Collection<Callback> mCallbacks = new ArrayList<Callback>(); 70afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 71b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie // Following constants indicate the user's choices of Phone book access settings 72b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie // User hasn't made any choice or settings app has wiped out the memory 73b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie final static int PHONEBOOK_ACCESS_UNKNOWN = 0; 74b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie // User has accepted the connection and let Settings app remember the decision 75b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie final static int PHONEBOOK_ACCESS_ALLOWED = 1; 76b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie // User has rejected the connection and let Settings app remember the decision 77b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie final static int PHONEBOOK_ACCESS_REJECTED = 2; 78b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 79b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie private final static String PHONEBOOK_PREFS_NAME = "bluetooth_phonebook_permission"; 80b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 81afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 82afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * When we connect to multiple profiles, we only want to display a single 83afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * error even if they all fail. This tracks that state. 84afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 85afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private boolean mIsConnectingErrorPossible; 86afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 872aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /** 88eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan * Last time a bt profile auto-connect was attempted. 89eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan * If an ACTION_UUID intent comes in within 902aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * MAX_UUID_DELAY_FOR_AUTO_CONNECT milliseconds, we will try auto-connect 912aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * again with the new UUIDs 922aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 93eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan private long mConnectAttempted; 942aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 95eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan // See mConnectAttempted 962aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000; 972aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 98dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby /** Auto-connect after pairing only if locally initiated. */ 99dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby private boolean mConnectAfterPairing; 10084905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh 101e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project /** 102f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * Describes the current device and profile for logging. 10384905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh * 104f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * @param profile Profile to describe 105f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * @return Description of the device and profile 106e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project */ 107436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private String describe(LocalBluetoothProfile profile) { 108f907e0bb891eca4d498871a1cc862117a462a076Adam Powell StringBuilder sb = new StringBuilder(); 109e79f990490de49b39097433707c2bae6d8238330Jake Hamby sb.append("Address:").append(mDevice); 110f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (profile != null) { 111436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby sb.append(" Profile:").append(profile); 112097ed6c671ed733c0967acc32e017020ede4575bMichael Chan } 113e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project 114f907e0bb891eca4d498871a1cc862117a462a076Adam Powell return sb.toString(); 115f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 11684905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh 117436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onProfileStateChanged(LocalBluetoothProfile profile, int newProfileState) { 118436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 119436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "onProfileStateChanged: profile " + profile + 120f907e0bb891eca4d498871a1cc862117a462a076Adam Powell " newProfileState " + newProfileState); 1216c97742c88303c65e68fe08257a7ccf841f03866Michael Chan } 1222ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji if (profile instanceof HeadsetProfile) { 1232ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji if (newProfileState == BluetoothProfile.STATE_CONNECTED) { 1242ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji if (BluetoothProfile.PRIORITY_AUTO_CONNECT != profile.getPreferred(mDevice)) 1252ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji mProfileManager.enableAutoConnectForHf(mDevice, true); 1262ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } else if (newProfileState == BluetoothProfile.STATE_DISCONNECTED) { 1272ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji // dont reset auto connect priority when bluetooth turned off 1282ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji if ((BluetoothAdapter.STATE_ON == mLocalAdapter.getBluetoothState()) 1292ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji || (BluetoothAdapter.STATE_TURNING_ON == mLocalAdapter.getBluetoothState())) { 1302ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji mProfileManager.enableAutoConnectForHf(mDevice, false); 1312ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } 1322ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } 1332ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } else if (profile instanceof A2dpProfile ) { 1342ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji if (newProfileState == BluetoothProfile.STATE_CONNECTED) { 1352ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji if (BluetoothProfile.PRIORITY_AUTO_CONNECT != profile.getPreferred(mDevice)) 1362ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji mProfileManager.enableAutoConnectForA2dp(mDevice,true); 1372ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } else if (newProfileState == BluetoothProfile.STATE_DISCONNECTED) { 1382ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji // dont reset auto connect priority when bluetooth turned off 1392ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji if ((BluetoothAdapter.STATE_ON == mLocalAdapter.getBluetoothState()) 1402ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji || (BluetoothAdapter.STATE_TURNING_ON == mLocalAdapter.getBluetoothState())) { 1412ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji mProfileManager.enableAutoConnectForA2dp(mDevice, false); 1422ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } 1432ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } 1442ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } 145e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project 14650e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.put(profile, newProfileState); 147436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (newProfileState == BluetoothProfile.STATE_CONNECTED) { 148f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (!mProfiles.contains(profile)) { 149c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mRemovedProfiles.remove(profile); 150f907e0bb891eca4d498871a1cc862117a462a076Adam Powell mProfiles.add(profile); 151c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby if (profile instanceof PanProfile && 152c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby ((PanProfile) profile).isLocalRoleNap(mDevice)) { 153c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby // Device doesn't support NAP, so remove PanProfile on disconnect 154c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mLocalNapRoleConnected = true; 155c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 156e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 157c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } else if (mLocalNapRoleConnected && profile instanceof PanProfile && 158c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby ((PanProfile) profile).isLocalRoleNap(mDevice) && 159c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby newProfileState == BluetoothProfile.STATE_DISCONNECTED) { 160c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby Log.d(TAG, "Removing PanProfile from device after NAP disconnect"); 161c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mProfiles.remove(profile); 162c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mRemovedProfiles.add(profile); 163c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mLocalNapRoleConnected = false; 164e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 165e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 166e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project 167b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie CachedBluetoothDevice(Context context, 168b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie LocalBluetoothAdapter adapter, 169b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie LocalBluetoothProfileManager profileManager, 170b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie BluetoothDevice device) { 171b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie mContext = context; 172436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter = adapter; 173436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileManager = profileManager; 174d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mDevice = device; 17550e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState = new HashMap<LocalBluetoothProfile, Integer>(); 176afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fillData(); 177afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 178afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 179436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void disconnect() { 180436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 181afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project disconnect(profile); 182afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 183afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 184afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 185436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void disconnect(LocalBluetoothProfile profile) { 186436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.disconnect(mDevice)) { 187436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 188d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh Log.d(TAG, "Command sent successfully:DISCONNECT " + describe(profile)); 189f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 190afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 191afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 192afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 193436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void connect(boolean connectAllProfiles) { 194436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 195afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return; 196afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 197afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 198eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mConnectAttempted = SystemClock.elapsedRealtime(); 1994bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connectWithoutResettingTimer(connectAllProfiles); 200eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 201eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan 202436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onBondingDockConnect() { 203582f1f84bb0ad4315ce17826672298c68f1c3b38Jake Hamby // Attempt to connect if UUIDs are available. Otherwise, 204582f1f84bb0ad4315ce17826672298c68f1c3b38Jake Hamby // we will connect when the ACTION_UUID intent arrives. 2054bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connect(false); 206b172cd5d232bd650d6efbb7d8b5e4cf9c213952fJaikumar Ganesh } 207b172cd5d232bd650d6efbb7d8b5e4cf9c213952fJaikumar Ganesh 20839ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby private void connectWithoutResettingTimer(boolean connectAllProfiles) { 209a0d39a39c2f53ebe858685c75c756b51dfac49daJake Hamby // Try to initialize the profiles if they were not. 210436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mProfiles.isEmpty()) { 2116e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // if mProfiles is empty, then do not invoke updateProfiles. This causes a race 2126e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // condition with carkits during pairing, wherein RemoteDevice.UUIDs have been updated 2136e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // from bluetooth stack but ACTION.uuid is not sent yet. 2146e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // Eventually ACTION.uuid will be received which shall trigger the connection of the 2156e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // various profiles 2166e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // If UUIDs are not available yet, connect will be happen 2176e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // upon arrival of the ACTION_UUID intent. 2186e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy Log.d(TAG, "No profiles. Maybe we will connect later"); 2196e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy return; 2202aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 2212aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 222afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 223afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 224afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 225eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan int preferredProfiles = 0; 226436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 22739ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) { 228436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.isPreferred(mDevice)) { 229b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan ++preferredProfiles; 230436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 231b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan } 232afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 233afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 234eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (DEBUG) Log.d(TAG, "Preferred profiles = " + preferredProfiles); 235afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 236eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (preferredProfiles == 0) { 237436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectAutoConnectableProfiles(); 238afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 239afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 240afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 241436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private void connectAutoConnectableProfiles() { 242436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 243436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 244436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 245afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 246afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 247afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 248436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 24939ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (profile.isAutoConnectable()) { 250436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby profile.setPreferred(mDevice, true); 251436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 252b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan } 253afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 254afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 255afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 256436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** 257436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Connect this device to the specified profile. 258436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 259436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param profile the profile to use with the remote device 260436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 261436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void connectProfile(LocalBluetoothProfile profile) { 262eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mConnectAttempted = SystemClock.elapsedRealtime(); 263afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 264afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 265436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 266f457e613d5d91322e0c967fb801899d55e3db9e5Syed Ibrahim M // Refresh the UI based on profile.connect() call 267f457e613d5d91322e0c967fb801899d55e3db9e5Syed Ibrahim M refresh(); 268afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 269afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 2702ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji synchronized void connectInt(LocalBluetoothProfile profile) { 271436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 272436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 273436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 274436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.connect(mDevice)) { 275436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 276d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh Log.d(TAG, "Command sent successfully:CONNECT " + describe(profile)); 277afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 278436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 279afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 280436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName); 281afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 282afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 283afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private boolean ensurePaired() { 28416cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly if (getBondState() == BluetoothDevice.BOND_NONE) { 285436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby startPairing(); 286afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return false; 287afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } else { 288afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 289afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 290afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 291afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 292436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean startPairing() { 293afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Pairing is unreliable while scanning, so cancel discovery 294436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mLocalAdapter.isDiscovering()) { 295436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter.cancelDiscovery(); 296afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 297afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 298d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if (!mDevice.createBond()) { 299436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 300afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 301dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby 302dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = true; // auto-connect after pairing 303436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return true; 304afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 305afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 306ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby /** 307ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby * Return true if user initiated pairing on this device. The message text is 308ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby * slightly different for local vs. remote initiated pairing dialogs. 309ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby */ 310ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby boolean isUserInitiatedPairing() { 311ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby return mConnectAfterPairing; 312ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby } 313ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby 314436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void unpair() { 31596b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan int state = getBondState(); 316afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 31796b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan if (state == BluetoothDevice.BOND_BONDING) { 318d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mDevice.cancelBondProcess(); 31996b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan } 32096b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan 32196b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan if (state != BluetoothDevice.BOND_NONE) { 322436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby final BluetoothDevice dev = mDevice; 323f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (dev != null) { 324f907e0bb891eca4d498871a1cc862117a462a076Adam Powell final boolean successful = dev.removeBond(); 325f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (successful) { 326436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 327f907e0bb891eca4d498871a1cc862117a462a076Adam Powell Log.d(TAG, "Command sent successfully:REMOVE_BOND " + describe(null)); 328f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 329436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else if (Utils.V) { 330f907e0bb891eca4d498871a1cc862117a462a076Adam Powell Log.v(TAG, "Framework rejected command immediately:REMOVE_BOND " + 331f907e0bb891eca4d498871a1cc862117a462a076Adam Powell describe(null)); 332f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 333f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 334afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 335afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 336afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 33750e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int getProfileConnectionState(LocalBluetoothProfile profile) { 33850e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh if (mProfileConnectionState == null || 33950e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.get(profile) == null) { 34050e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh // If cache is empty make the binder call to get the state 34150e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int state = profile.getConnectionStatus(mDevice); 34250e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.put(profile, state); 34350e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh } 34450e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh return mProfileConnectionState.get(profile); 34550e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh } 34650e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh 347436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // TODO: do any of these need to run async on a background thread? 348afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fillData() { 349afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchName(); 350afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchBtClass(); 3512aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan updateProfiles(); 352b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie fetchPhonebookPermissionChoice(); 353afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 354afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mVisible = false; 355afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 356afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 357afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 358436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice getDevice() { 359d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice; 360afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 361afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 362436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby String getName() { 363afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return mName; 364afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 365afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 366436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void setName(String name) { 367d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh if (!mName.equals(name)) { 368d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh if (TextUtils.isEmpty(name)) { 369c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby // TODO: use friendly name for unknown device (bug 1181856) 370d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mName = mDevice.getAddress(); 371d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } else { 372d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh mName = name; 3732036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie mDevice.setAlias(name); 374d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 375d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh dispatchAttributesChanged(); 376d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 377d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 378d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh 379436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refreshName() { 380afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchName(); 381afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 382afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 383afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 384afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fetchName() { 3852036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie mName = mDevice.getAliasName(); 386afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 387afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (TextUtils.isEmpty(mName)) { 388d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mName = mDevice.getAddress(); 389436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) Log.d(TAG, "Device has no name (yet), use address: " + mName); 390afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 391afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 392afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 393436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refresh() { 394afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 395afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 396afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 397436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isVisible() { 398afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return mVisible; 399afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 400afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 401afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project void setVisible(boolean visible) { 402afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (mVisible != visible) { 403afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mVisible = visible; 404afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 405afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 406afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 407afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 408436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int getBondState() { 409d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.getBondState(); 410afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 411afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 412afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project void setRssi(short rssi) { 413afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (mRssi != rssi) { 414afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mRssi = rssi; 415afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 416afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 417afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 418afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 419afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 420afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Checks whether we are connected to this device (any profile counts). 421afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 422afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * @return Whether it is connected. 423afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 424436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isConnected() { 425436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 42650e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 427436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (status == BluetoothProfile.STATE_CONNECTED) { 428afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 429afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 430afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 431afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 432afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return false; 433afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 434afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 435436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isConnectedProfile(LocalBluetoothProfile profile) { 43650e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 437436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return status == BluetoothProfile.STATE_CONNECTED; 438c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby 439c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby } 440c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby 441436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isBusy() { 442436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 44350e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 444436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (status == BluetoothProfile.STATE_CONNECTING 445436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby || status == BluetoothProfile.STATE_DISCONNECTING) { 446afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 447afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 448afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 449436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return getBondState() == BluetoothDevice.BOND_BONDING; 450cde015b3d424b0d83030f11432ad0a0589014bd5Jake Hamby } 451cde015b3d424b0d83030f11432ad0a0589014bd5Jake Hamby 452afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 453afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Fetches a new value for the cached BT class. 454afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 455afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fetchBtClass() { 456d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mBtClass = mDevice.getBluetoothClass(); 4572aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 4582aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4592aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan private boolean updateProfiles() { 4602aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan ParcelUuid[] uuids = mDevice.getUuids(); 4612aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan if (uuids == null) return false; 4622aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 463436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby ParcelUuid[] localUuids = mLocalAdapter.getUuids(); 464498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh if (localUuids == null) return false; 465498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh 466c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mProfileManager.updateProfiles(uuids, localUuids, mProfiles, mRemovedProfiles); 4672aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4682aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan if (DEBUG) { 4692036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie Log.e(TAG, "updating profiles for " + mDevice.getAliasName()); 4702aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan BluetoothClass bluetoothClass = mDevice.getBluetoothClass(); 4712aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4728c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh if (bluetoothClass != null) Log.v(TAG, "Class: " + bluetoothClass.toString()); 4738c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh Log.v(TAG, "UUID:"); 474436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (ParcelUuid uuid : uuids) { 475436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.v(TAG, " " + uuid); 4762aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 477b20dd917e2d29045225985baa980a2a8e22e10fcNick Pelly } 4782aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan return true; 479afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 480afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 481afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 482afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Refreshes the UI for the BT class, including fetching the latest value 483afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * for the class. 484afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 485436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refreshBtClass() { 486afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchBtClass(); 487afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 488afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 489afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 4902aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /** 4912aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * Refreshes the UI when framework alerts us of a UUID change. 4922aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 493436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onUuidChanged() { 4942aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan updateProfiles(); 4952aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 496eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (DEBUG) { 497eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan Log.e(TAG, "onUuidChanged: Time since last connect" 498eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan + (SystemClock.elapsedRealtime() - mConnectAttempted)); 499eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 5002aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 5012aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /* 5022aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * If a connect was attempted earlier without any UUID, we will do the 5032aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * connect now. 5042aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 505436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!mProfiles.isEmpty() 506eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan && (mConnectAttempted + MAX_UUID_DELAY_FOR_AUTO_CONNECT) > SystemClock 5072aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan .elapsedRealtime()) { 50839ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby connectWithoutResettingTimer(false); 5092aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 5102aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan dispatchAttributesChanged(); 5112aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 5122aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 513436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onBondingStateChanged(int bondState) { 514eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (bondState == BluetoothDevice.BOND_NONE) { 515eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mProfiles.clear(); 516dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = false; // cancel auto-connect 517b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie setPhonebookPermissionChoice(PHONEBOOK_ACCESS_UNKNOWN); 518eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 5191308453b16c2ca85a456bd4bb7f3c71c916bd83eMichael Chan 520eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan refresh(); 521dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby 522dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby if (bondState == BluetoothDevice.BOND_BONDED) { 523dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby if (mDevice.isBluetoothDock()) { 524dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby onBondingDockConnect(); 525dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } else if (mConnectAfterPairing) { 5264bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connect(false); 527dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } 528dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = false; 529dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } 530eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 531eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan 532436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void setBtClass(BluetoothClass btClass) { 53316cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly if (btClass != null && mBtClass != btClass) { 534d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh mBtClass = btClass; 535d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh dispatchAttributesChanged(); 536d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 537d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 538d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh 539436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothClass getBtClass() { 540436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mBtClass; 541afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 542afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 543436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> getProfiles() { 544436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return Collections.unmodifiableList(mProfiles); 54548e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani } 546afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 547436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> getConnectableProfiles() { 548436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> connectableProfiles = 549436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new ArrayList<LocalBluetoothProfile>(); 550436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 55139ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (profile.isConnectable()) { 552e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan connectableProfiles.add(profile); 553e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 554e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 555e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan return connectableProfiles; 556e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 557e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan 558c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby List<LocalBluetoothProfile> getRemovedProfiles() { 559c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby return mRemovedProfiles; 560c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 561c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 562436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void registerCallback(Callback callback) { 563afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 564afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mCallbacks.add(callback); 565afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 566afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 567afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 568436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void unregisterCallback(Callback callback) { 569afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 570afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mCallbacks.remove(callback); 571afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 572afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 573afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 574afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void dispatchAttributesChanged() { 575afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 576afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project for (Callback callback : mCallbacks) { 577c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby callback.onDeviceAttributesChanged(); 578afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 579afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 580afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 581afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 582afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 583afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public String toString() { 584d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.toString(); 585afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 586afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 587afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 588afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public boolean equals(Object o) { 589d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if ((o == null) || !(o instanceof CachedBluetoothDevice)) { 590436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 591afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 592d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.equals(((CachedBluetoothDevice) o).mDevice); 593afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 594afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 595afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 596afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public int hashCode() { 597d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.getAddress().hashCode(); 598afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 599afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 600436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // This comparison uses non-final fields so the sort order may change 601436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // when device attributes change (such as bonding state). Settings 602436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // will completely refresh the device list when this happens. 603d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly public int compareTo(CachedBluetoothDevice another) { 604afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Connected above not connected 605436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int comparison = (another.isConnected() ? 1 : 0) - (isConnected() ? 1 : 0); 606afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 607afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 608afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Paired above not paired 609afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = (another.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0) - 610afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project (getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0); 611afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 612afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 613afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Visible above not visible 614afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = (another.mVisible ? 1 : 0) - (mVisible ? 1 : 0); 615afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 616afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 617afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Stronger signal above weaker signal 618afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = another.mRssi - mRssi; 619afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 620afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 621afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Fallback on name 622436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mName.compareTo(another.mName); 623afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 624afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 625afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public interface Callback { 626c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby void onDeviceAttributesChanged(); 627afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 628b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 629b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie int getPhonebookPermissionChoice() { 630b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie return mPhonebookPermissionChoice; 631b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 632b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 633b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie void setPhonebookPermissionChoice(int permissionChoice) { 634b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie SharedPreferences.Editor editor = 635b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie mContext.getSharedPreferences(PHONEBOOK_PREFS_NAME, Context.MODE_PRIVATE).edit(); 636b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie if (permissionChoice == PHONEBOOK_ACCESS_UNKNOWN) { 637b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie editor.remove(mDevice.getAddress()); 638b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } else { 639b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie editor.putInt(mDevice.getAddress(), permissionChoice); 640b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 641b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie editor.commit(); 642b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie mPhonebookPermissionChoice = permissionChoice; 643b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 644b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 645b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie private void fetchPhonebookPermissionChoice() { 646b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie SharedPreferences preference = mContext.getSharedPreferences(PHONEBOOK_PREFS_NAME, 647b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie Context.MODE_PRIVATE); 648b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie mPhonebookPermissionChoice = preference.getInt(mDevice.getAddress(), 649b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie PHONEBOOK_ACCESS_UNKNOWN); 650b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 651b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 652afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project} 653