BluetoothService.java revision 740e39be6af3e366a4b82c030b5ea67ab144b42a
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TODO: Move this to 19bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * java/services/com/android/server/BluetoothService.java 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and make the contructor package private again. 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.server; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.BluetoothAdapter; 28dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganeshimport android.bluetooth.BluetoothClass; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothDevice; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothHeadset; 319b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganeshimport android.bluetooth.BluetoothProfileConnectionState; 3224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pellyimport android.bluetooth.BluetoothSocket; 3310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganeshimport android.bluetooth.BluetoothUuid; 34bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.IBluetooth; 3516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport android.bluetooth.IBluetoothCallback; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 416e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganeshimport android.content.SharedPreferences; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 443fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.IBinder; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 463fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.ParcelUuid; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 48105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.os.ServiceManager; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemService; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 53d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganeshimport com.android.internal.app.IBatteryStats; 54d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 553fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedInputStream; 56c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganeshimport java.io.BufferedReader; 573fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedWriter; 58c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganeshimport java.io.DataInputStream; 59c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganeshimport java.io.File; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 613fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileInputStream; 623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileNotFoundException; 63c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganeshimport java.io.FileOutputStream; 643fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileWriter; 653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.IOException; 66c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganeshimport java.io.InputStreamReader; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.UnsupportedEncodingException; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 7216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport java.util.Iterator; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 75bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellypublic class BluetoothService extends IBluetooth.Stub { 76bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private static final String TAG = "BluetoothService"; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean DBG = true; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNativeData; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BluetoothEventLoop mEventLoop; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsAirplaneSensitive; 8244303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey private boolean mIsAirplaneToggleable; 83105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private int mBluetoothState; 84997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly private boolean mRestart = false; // need to call enable() after disable() 85bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private boolean mIsDiscovering; 86997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 87bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private BluetoothAdapter mAdapter; // constant after init() 88997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly private final BondState mBondState = new BondState(); // local cache of bondings 89105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private final IBatteryStats mBatteryStats; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 953fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_ADDRESS_PATH = "/sys/class/switch/dock/bt_addr"; 963fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_PIN_PATH = "/sys/class/switch/dock/bt_pin"; 973fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 986e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address"; 996e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings"; 1006e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 101105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static final int MESSAGE_REGISTER_SDP_RECORDS = 1; 102105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static final int MESSAGE_FINISH_DISABLE = 2; 1031caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private static final int MESSAGE_UUID_INTENT = 3; 10412835478ee687a493d1b5882e67b6725bd539c26Nick Pelly private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 4; 1051caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 1061caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // The timeout used to sent the UUIDs Intent 1071caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // This timeout should be greater than the page timeout 1081caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private static final int UUID_INTENT_DELAY = 6000; 109105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 11016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** Always retrieve RFCOMM channel for these SDP UUIDs */ 11116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static final ParcelUuid[] RFCOMM_UUIDS = { 11216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.Handsfree, 11316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.HSP, 11416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.ObexObjectPush }; 11516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1169b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh // TODO(): Optimize all these string handling 117bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private final Map<String, String> mAdapterProperties; 11816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<String, Map<String, String>> mDeviceProperties; 119d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 12016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache; 12116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final ArrayList<String> mUuidIntentTracker; 12216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker; 1231caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private final HashMap<Integer, Integer> mServiceRecordToPid; 12524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 1269b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private final HashMap<String, BluetoothProfileConnectionState> mProfileConnectionMgr; 1279b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 1289b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private BluetoothA2dpService mA2dpService; 1293fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static String mDockAddress; 1303fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private String mDockPin; 1313fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 13216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static class RemoteService { 13316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public String address; 13416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public ParcelUuid uuid; 13516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public RemoteService(String address, ParcelUuid uuid) { 13616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.address = address; 13716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.uuid = uuid; 13816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 13916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly @Override 14016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public boolean equals(Object o) { 14116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (o instanceof RemoteService) { 14216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = (RemoteService)o; 14316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return address.equals(service.address) && uuid.equals(service.uuid); 14416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 14516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 14616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 1475f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root 1485f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root @Override 1495f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root public int hashCode() { 1505f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root int hash = 1; 1515f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (address == null ? 0 : address.hashCode()); 1525f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (uuid == null ? 0 : uuid.hashCode()); 1535f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root return hash; 1545f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root } 15516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 15616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project classInitNative(); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 161bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public BluetoothService(Context context) { 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 163105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 164105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Need to do this in place of: 165105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // mBatteryStats = BatteryStatsService.getService(); 166105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Since we can not import BatteryStatsService from here. This class really needs to be 167105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // moved to java/services/com/android/server/ 168105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initializeNativeDataNative(); 171ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 172ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (isEnabledNative() == 1) { 173ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Log.w(TAG, "Bluetooth daemons already running - runtime restart? "); 174ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project disableNative(); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 176ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 177de893f550301a60274e87aa8168225e7a7a42184Nick Pelly mBluetoothState = BluetoothAdapter.STATE_OFF; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsDiscovering = false; 179bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties = new HashMap<String, String>(); 180bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties = new HashMap<String, Map<String,String>>(); 18110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 18210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>(); 1831caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker = new ArrayList<String>(); 18416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>(); 18524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid = new HashMap<Integer, Integer>(); 1869b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh mProfileConnectionMgr = new HashMap<String, BluetoothProfileConnectionState>(); 1873fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1883fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh IntentFilter filter = new IntentFilter(); 1896e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh registerForAirplaneMode(filter); 1906e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 1913fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh filter.addAction(Intent.ACTION_DOCK_EVENT); 1926e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.registerReceiver(mReceiver, filter); 1933fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 1943fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1959b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public static synchronized String readDockBluetoothAddress() { 1963fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (mDockAddress != null) return mDockAddress; 1973fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1983fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedInputStream file = null; 1993fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh String dockAddress; 2003fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2013fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file = new BufferedInputStream(new FileInputStream(DOCK_ADDRESS_PATH)); 2023fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh byte[] address = new byte[17]; 2033fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.read(address); 2043fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = new String(address); 2053fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = dockAddress.toUpperCase(); 2063fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (BluetoothAdapter.checkBluetoothAddress(dockAddress)) { 2073fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = dockAddress; 2083fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockAddress; 2093fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } else { 2103fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("CheckBluetoothAddress failed for car dock address:" + dockAddress); 2113fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2123fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2133fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("FileNotFoundException while trying to read dock address"); 2143fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2153fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("IOException while trying to read dock address"); 2163fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 2173fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (file != null) { 2183fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2193fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.close(); 2203fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2213fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 2223fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2233fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2243fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2253fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = null; 2263fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return null; 2273fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2283fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2293fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private synchronized boolean writeDockPin() { 2303fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedWriter out = null; 2313fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2323fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out = new BufferedWriter(new FileWriter(DOCK_PIN_PATH)); 2333fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2343fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Generate a random 4 digit pin between 0000 and 9999 2353fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // This is not truly random but good enough for our purposes. 2363fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh int pin = (int) Math.floor(Math.random() * 10000); 2373fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2383fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = String.format("%04d", pin); 2393fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.write(mDockPin); 2403fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return true; 2413fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2423fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("FileNotFoundException while trying to write dock pairing pin"); 2433fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2443fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("IOException while while trying to write dock pairing pin"); 2453fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 2463fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (out != null) { 2473fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2483fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.close(); 2493fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2503fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 2513fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2523fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2533fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = null; 2553fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 2563fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2573fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2583fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh /*package*/ synchronized String getDockPin() { 2593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockPin; 260bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly } 261bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly 262bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public synchronized void initAfterRegistration() { 263f242b7b931898856bcbcb7ec36cacf43098ba544Nick Pelly mAdapter = BluetoothAdapter.getDefaultAdapter(); 264bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mEventLoop = new BluetoothEventLoop(mContext, mAdapter, this); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 2696e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.unregisterReceiver(mReceiver); 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cleanupNativeDataNative(); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isEnabled() { 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2798c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh return isEnabledInternal(); 2808c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh } 2818c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 2828c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh private boolean isEnabledInternal() { 283de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return mBluetoothState == BluetoothAdapter.STATE_ON; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 286105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public int getBluetoothState() { 287105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 288105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return mBluetoothState; 289105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 290105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 291105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth and disable BT in settings. Returns true on success. 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean disable() { 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return disable(true); 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth. Returns true on success. 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 302e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly * @param saveSetting If true, persist the new setting 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean disable(boolean saveSetting) { 305e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 307105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project switch (mBluetoothState) { 308de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_OFF: 309105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 310de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_ON: 311105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 312105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project default: 313105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return false; 314105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEnableThread != null && mEnableThread.isAlive()) { 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 318de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF); 319bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.removeMessages(MESSAGE_REGISTER_SDP_RECORDS); 320105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 321105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Allow 3 seconds for profiles to gracefully disconnect 322105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // TODO: Introduce a callback mechanism so that each profile can notify 323bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly // BluetoothService when it is done shutting down 324105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mHandler.sendMessageDelayed( 325105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000); 326105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 327105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 328105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 329105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 330105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private synchronized void finishDisable(boolean saveSetting) { 331de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_TURNING_OFF) { 332105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEventLoop.stop(); 335d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh tearDownNativeDataNative(); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project disableNative(); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mark in progress bondings as cancelled 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) { 340005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // update mode 345de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 346de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 349105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mIsDiscovering = false; 350bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.clear(); 35124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.clear(); 352105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (saveSetting) { 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project persistBluetoothOnSetting(false); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 356105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 357de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_OFF); 358105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 359105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Log bluetooth off to battery stats. 360105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project long ident = Binder.clearCallingIdentity(); 361105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project try { 362105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats.noteBluetoothOff(); 363105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } catch (RemoteException e) { 364105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } finally { 365105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Binder.restoreCallingIdentity(ident); 366105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 367997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 368997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (mRestart) { 369997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 370997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly enable(); 371997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 374105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /** Bring up BT and persist BT on in settings */ 375105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public boolean enable() { 376105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return enable(true); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enable this Bluetooth device, asynchronously. 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This turns on/off the underlying hardware. 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 383105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @param saveSetting If true, persist the new state of BT in settings 384105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @return True on success (so far) 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 386105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public synchronized boolean enable(boolean saveSetting) { 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Airplane mode can prevent Bluetooth radio from being turned on. 39144303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 394de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_OFF) { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEnableThread != null && mEnableThread.isAlive()) { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 400de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_TURNING_ON); 401105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mEnableThread = new EnableThread(saveSetting); 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEnableThread.start(); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 406997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /** Forcibly restart Bluetooth if it is on */ 407997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /* package */ synchronized void restart() { 408de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_ON) { 409997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly return; 410997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 411997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = true; 412997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (!disable(false)) { 413997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 414997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 415d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 416997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 417105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private synchronized void setBluetoothState(int state) { 418105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (state == mBluetoothState) { 419105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 420105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 421105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 422105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (DBG) log("Bluetooth state " + mBluetoothState + " -> " + state); 423105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 424de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 425de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mBluetoothState); 426de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_STATE, state); 427105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 428105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 429105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBluetoothState = state; 430105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 431105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 432105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 433105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Handler mHandler = new Handler() { 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 438105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case MESSAGE_REGISTER_SDP_RECORDS: 4398c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) { 440bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly return; 441bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly } 442bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // SystemService.start() forks sdptool to register service 443bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // records. It can fail to register some records if it is 444bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // forked multiple times in a row, probably because there is 445bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // some race in sdptool or bluez when operated in parallel. 446bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // As a workaround, delay 500ms between each fork of sdptool. 447bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // TODO: Don't fork sdptool in order to regsiter service 448bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // records, use a DBUS call instead. 449bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly switch (msg.arg1) { 450bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 1: 45177b4ad0e496941a28382eb938a05831f1f8d2d4aJaikumar Ganesh Log.d(TAG, "Registering hfag record"); 45277b4ad0e496941a28382eb938a05831f1f8d2d4aJaikumar Ganesh SystemService.start("hfag"); 453bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 454bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 2, -1), 500); 455bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 456bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 2: 45777b4ad0e496941a28382eb938a05831f1f8d2d4aJaikumar Ganesh Log.d(TAG, "Registering hsag record"); 45877b4ad0e496941a28382eb938a05831f1f8d2d4aJaikumar Ganesh SystemService.start("hsag"); 459bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 460bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 3, -1), 500); 461bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 462bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 3: 463bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly Log.d(TAG, "Registering opush record"); 46403c707ab6fc97e99b1603b8d6edc604dbea3cd6fNick Pelly SystemService.start("opush"); 465bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 466bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 4, -1), 500); 467bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 468bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 4: 469bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly Log.d(TAG, "Registering pbap record"); 47067542964876aa7e4216e8f69f21dda68e7463b9aJaikumar Ganesh SystemService.start("pbap"); 471bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 473105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 474105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case MESSAGE_FINISH_DISABLE: 475105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project finishDisable(msg.arg1 != 0); 476105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 4771caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh case MESSAGE_UUID_INTENT: 4781caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String address = (String)msg.obj; 47916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (address != null) { 4801caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh sendUuidIntent(address); 48116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly makeServiceChannelCallbacks(address); 48216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 4831caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh break; 48412835478ee687a493d1b5882e67b6725bd539c26Nick Pelly case MESSAGE_DISCOVERABLE_TIMEOUT: 48512835478ee687a493d1b5882e67b6725bd539c26Nick Pelly int mode = msg.arg1; 4868c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (isEnabledInternal()) { 48712835478ee687a493d1b5882e67b6725bd539c26Nick Pelly // TODO: Switch back to the previous scan mode 48812835478ee687a493d1b5882e67b6725bd539c26Nick Pelly // This is ok for now, because we only use 48912835478ee687a493d1b5882e67b6725bd539c26Nick Pelly // CONNECTABLE and CONNECTABLE_DISCOVERABLE 49012835478ee687a493d1b5882e67b6725bd539c26Nick Pelly setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, -1); 49112835478ee687a493d1b5882e67b6725bd539c26Nick Pelly } 49212835478ee687a493d1b5882e67b6725bd539c26Nick Pelly break; 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private EnableThread mEnableThread; 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class EnableThread extends Thread { 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean mSaveSetting; 501105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public EnableThread(boolean saveSetting) { 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSaveSetting = saveSetting; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean res = (enableNative() == 0); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res) { 507b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project int retryCount = 2; 508b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project boolean running = false; 509b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project while ((retryCount-- > 0) && !running) { 510b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mEventLoop.start(); 511105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // it may take a momement for the other thread to do its 512b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // thing. Check periodically for a while. 513b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project int pollCount = 5; 514b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project while ((pollCount-- > 0) && !running) { 515b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (mEventLoop.isEventLoopRunning()) { 516b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project running = true; 517b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project break; 518b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 519b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project try { 520b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project Thread.sleep(100); 521b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } catch (InterruptedException e) {} 522b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 523b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 524b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (!running) { 525b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project log("bt EnableThread giving up"); 526b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project res = false; 527b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project disableNative(); 528b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res) { 533d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!setupNativeDataNative()) { 534d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return; 535d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSaveSetting) { 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project persistBluetoothOnSetting(true); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsDiscovering = false; 540c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mBondState.readAutoPairingData(); 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.loadBondState(); 5429b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh initProfileState(); 543bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 544bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 1, -1), 3000); 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 546105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Log bluetooth on to battery stats. 547105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project long ident = Binder.clearCallingIdentity(); 548105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project try { 549105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats.noteBluetoothOn(); 550105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } catch (RemoteException e) { 551105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } finally { 552105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Binder.restoreCallingIdentity(ident); 553105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 555105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 556105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mEnableThread = null; 557105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 558105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project setBluetoothState(res ? 559de893f550301a60274e87aa8168225e7a7a42184Nick Pelly BluetoothAdapter.STATE_ON : 560de893f550301a60274e87aa8168225e7a7a42184Nick Pelly BluetoothAdapter.STATE_OFF); 561105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 562b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (res) { 563105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Update mode 564d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String[] propVal = {"Pairable", getProperty("Pairable")}; 565d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mEventLoop.onPropertyChanged(propVal); 566b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 567b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 56844303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 5695c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa disable(false); 5705c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa } 5715c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void persistBluetoothOnSetting(boolean bluetoothOn) { 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long origCallerIdentityToken = Binder.clearCallingIdentity(); 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON, 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bluetoothOn ? 1 : 0); 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(origCallerIdentityToken); 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ BondState getBondState() { 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState; 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** local cache of bonding state. 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* we keep our own state to track the intermediate state BONDING, which 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* bluez does not track. 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * All addreses must be passed in upper case. 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class BondState { 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final HashMap<String, Integer> mState = new HashMap<String, Integer>(); 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>(); 594c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 595c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private static final String AUTO_PAIRING_BLACKLIST = 596c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh "/etc/bluetooth/auto_pairing.conf"; 597c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private static final String DYNAMIC_AUTO_PAIRING_BLACKLIST = 598c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh "/data/misc/bluetooth/dynamic_auto_pairing.conf"; 599c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private ArrayList<String> mAutoPairingAddressBlacklist; 600c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private ArrayList<String> mAutoPairingExactNameBlacklist; 601c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private ArrayList<String> mAutoPairingPartialNameBlacklist; 602c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh // Addresses added to blacklist dynamically based on usage. 603c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private ArrayList<String> mAutoPairingDynamicAddressBlacklist; 604c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 605482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh 6062092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // If this is an outgoing connection, store the address. 6072092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // There can be only 1 pending outgoing connection at a time, 6082092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh private String mPendingOutgoingBonding; 6092092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 6102092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh private synchronized void setPendingOutgoingBonding(String address) { 6112092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mPendingOutgoingBonding = address; 6122092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 6132092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 6142092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh public synchronized String getPendingOutgoingBonding() { 6152092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh return mPendingOutgoingBonding; 6162092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 6172092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void loadBondState() { 619de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_TURNING_ON) { 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 622d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String []bonds = null; 623b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh String val = getPropertyInternal("Devices"); 624d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (val != null) { 625d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh bonds = val.split(","); 626d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bonds == null) { 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.clear(); 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log("found " + bonds.length + " bonded devices"); 632d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh for (String device : bonds) { 633d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mState.put(getAddressFromObjectPath(device).toUpperCase(), 634d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh BluetoothDevice.BOND_BONDED); 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setBondState(String address, int state) { 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setBondState(address, state, 0); 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** reason is ignored unless state == BOND_NOT_BONDED */ 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setBondState(String address, int state, int reason) { 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oldState = getBondState(address); 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oldState == state) { 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6482092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 6492092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // Check if this was an pending outgoing bonding. 6502092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // If yes, reset the state. 6512092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (oldState == BluetoothDevice.BOND_BONDING) { 6522092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (address.equals(mPendingOutgoingBonding)) { 6532092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mPendingOutgoingBonding = null; 6542092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 6552092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 6562092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 6579b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state == BluetoothDevice.BOND_BONDED) { 6589b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh addProfileState(address); 6599b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } else if (state == BluetoothDevice.BOND_NONE) { 6609b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh removeProfileState(address); 6619b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 6629b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log(address + " bond state " + oldState + " -> " + state + " (" + 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reason + ")"); 665005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly Intent intent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED); 666005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 667005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, state); 668005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, oldState); 669005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (state == BluetoothDevice.BOND_NONE) { 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (reason <= 0) { 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "setBondState() called to unbond device, but reason code is " + 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "invalid. Overriding reason code with BOND_RESULT_REMOVED"); 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reason = BluetoothDevice.UNBOND_REASON_REMOVED; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 675005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_REASON, reason); 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.remove(address); 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.put(address, state); 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isAutoPairingBlacklisted(String address) { 685c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingAddressBlacklist != null) { 686c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh for (String blacklistAddress : mAutoPairingAddressBlacklist) { 687c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (address.startsWith(blacklistAddress)) return true; 688c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 690482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh 691c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingDynamicAddressBlacklist != null) { 692c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh for (String blacklistAddress: mAutoPairingDynamicAddressBlacklist) { 693c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (address.equals(blacklistAddress)) return true; 694c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 695c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 696482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh String name = getRemoteName(address); 697482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh if (name != null) { 698c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingExactNameBlacklist != null) { 699c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh for (String blacklistName : mAutoPairingExactNameBlacklist) { 700c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (name.equals(blacklistName)) return true; 701c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 702738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh } 703738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh 704c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingPartialNameBlacklist != null) { 705c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh for (String blacklistName : mAutoPairingPartialNameBlacklist) { 706c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (name.startsWith(blacklistName)) return true; 707c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 708482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh } 709482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh } 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getBondState(String address) { 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer state = mState.get(address); 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == null) { 716005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly return BluetoothDevice.BOND_NONE; 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return state.intValue(); 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 721e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh /*package*/ synchronized String[] listInState(int state) { 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<String> result = new ArrayList<String>(mState.size()); 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Map.Entry<String, Integer> e : mState.entrySet()) { 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (e.getValue().intValue() == state) { 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result.add(e.getKey()); 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result.toArray(new String[result.size()]); 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void addAutoPairingFailure(String address) { 732c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingDynamicAddressBlacklist == null) { 733c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingDynamicAddressBlacklist = new ArrayList<String>(); 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 735c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 736c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh updateAutoPairingData(address); 737c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingDynamicAddressBlacklist.add(address); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean isAutoPairingAttemptsInProgress(String address) { 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getAttempt(address) != 0; 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void clearPinAttempts(String address) { 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPinAttempt.remove(address); 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean hasAutoPairingFailed(String address) { 749c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingDynamicAddressBlacklist == null) return false; 750c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 751c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh return mAutoPairingDynamicAddressBlacklist.contains(address); 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getAttempt(String address) { 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer attempt = mPinAttempt.get(address); 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (attempt == null) { 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return attempt.intValue(); 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void attempt(String address) { 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer attempt = mPinAttempt.get(address); 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newAttempt; 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (attempt == null) { 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newAttempt = 1; 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newAttempt = attempt.intValue() + 1; 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPinAttempt.put(address, new Integer(newAttempt)); 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 773c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private void copyAutoPairingData() { 774c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh File file = null; 775c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh FileInputStream in = null; 776c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh FileOutputStream out = null; 777c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 778c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh file = new File(DYNAMIC_AUTO_PAIRING_BLACKLIST); 779c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (file.exists()) return; 780c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 781c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh in = new FileInputStream(AUTO_PAIRING_BLACKLIST); 782c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh out= new FileOutputStream(DYNAMIC_AUTO_PAIRING_BLACKLIST); 783c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 784c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh byte[] buf = new byte[1024]; 785c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh int len; 786c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh while ((len = in.read(buf)) > 0) { 787c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh out.write(buf, 0, len); 788c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 789c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (FileNotFoundException e) { 790c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("FileNotFoundException: in copyAutoPairingData"); 791c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) { 792c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("IOException: in copyAutoPairingData"); 793c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } finally { 794c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 795c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (in != null) in.close(); 796c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (out != null) out.close(); 797c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) {} 798c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 799c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 800c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 801c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh public void readAutoPairingData() { 802c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingAddressBlacklist != null) return; 803c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh copyAutoPairingData(); 804c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh FileInputStream fstream = null; 805c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 806c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh fstream = new FileInputStream(DYNAMIC_AUTO_PAIRING_BLACKLIST); 807c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh DataInputStream in = new DataInputStream(fstream); 808c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh BufferedReader file = new BufferedReader(new InputStreamReader(in)); 809c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh String line; 810c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh while((line = file.readLine()) != null) { 811c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh line = line.trim(); 812c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (line.length() == 0 || line.startsWith("//")) continue; 813c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh String[] value = line.split("="); 814c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (value != null && value.length == 2) { 815c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh String[] val = value[1].split(","); 816c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (value[0].equalsIgnoreCase("AddressBlacklist")) { 817c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingAddressBlacklist = 818c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh new ArrayList<String>(Arrays.asList(val)); 819c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } else if (value[0].equalsIgnoreCase("ExactNameBlacklist")) { 820c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingExactNameBlacklist = 821c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh new ArrayList<String>(Arrays.asList(val)); 822c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } else if (value[0].equalsIgnoreCase("PartialNameBlacklist")) { 823c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingPartialNameBlacklist = 824c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh new ArrayList<String>(Arrays.asList(val)); 825c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } else if (value[0].equalsIgnoreCase("DynamicAddressBlacklist")) { 826c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingDynamicAddressBlacklist = 827c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh new ArrayList<String>(Arrays.asList(val)); 828c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } else { 829c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh Log.e(TAG, "Error parsing Auto pairing blacklist file"); 830c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 831c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 832c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 833c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (FileNotFoundException e) { 834c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("FileNotFoundException: readAutoPairingData" + e.toString()); 835c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) { 836c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("IOException: readAutoPairingData" + e.toString()); 837c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } finally { 838c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (fstream != null) { 839c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 840c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh fstream.close(); 841c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) { 842c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh // Ignore 843c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 844c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 845c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 846c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 847c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 848c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh // This function adds a bluetooth address to the auto pairing blacklis 849c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh // file. These addresses are added to DynamicAddressBlacklistSection 850c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private void updateAutoPairingData(String address) { 851c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh BufferedWriter out = null; 852c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 853c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh out = new BufferedWriter(new FileWriter(DYNAMIC_AUTO_PAIRING_BLACKLIST, true)); 854c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh StringBuilder str = new StringBuilder(); 855c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingDynamicAddressBlacklist.size() == 0) { 856c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh str.append("DynamicAddressBlacklist="); 857c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 858c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh str.append(address); 859c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh str.append(","); 860c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh out.write(str.toString()); 861c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (FileNotFoundException e) { 862c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("FileNotFoundException: updateAutoPairingData" + e.toString()); 863c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) { 864c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("IOException: updateAutoPairingData" + e.toString()); 865c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } finally { 866c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (out != null) { 867c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 868c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh out.close(); 869c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) { 870c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh // Ignore 871c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 872c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 873c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 874c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String toBondStateString(int bondState) { 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (bondState) { 879005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly case BluetoothDevice.BOND_NONE: 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "not bonded"; 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDING: 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonding"; 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDED: 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonded"; 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "??????"; 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8909519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh /*package*/ synchronized boolean isAdapterPropertiesEmpty() { 8919519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh return mAdapterProperties.isEmpty(); 8929519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh } 8939519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh 894d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/synchronized void getAllProperties() { 8958c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 897bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.clear(); 898d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 899d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String properties[] = (String [])getAdapterPropertiesNative(); 900d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The String Array consists of key-value pairs. 901d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (properties == null) { 902d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "*Error*: GetAdapterProperties returned NULL"); 903d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return; 904d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 905d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 9068bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int i = 0; i < properties.length; i++) { 9078bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh String name = properties[i]; 908efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh String newValue = null; 9098bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh int len; 9108bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (name == null) { 9118bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh Log.e(TAG, "Error:Adapter Property at index" + i + "is null"); 9128bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh continue; 9138bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 9148bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (name.equals("Devices")) { 915efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh StringBuilder str = new StringBuilder(); 9168bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh len = Integer.valueOf(properties[++i]); 9178bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int j = 0; j < len; j++) { 918efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(properties[++i]); 919efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(","); 920efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh } 921efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh if (len > 0) { 922efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh newValue = str.toString(); 9238bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 9248bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } else { 9258bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh newValue = properties[++i]; 9268bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 927bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.put(name, newValue); 928d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 929d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 930d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Add adapter object path property. 931d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String adapterPath = getAdapterPathNative(); 932d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (adapterPath != null) 933bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.put("ObjectPath", adapterPath + "/dev_"); 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 936d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ synchronized void setProperty(String name, String value) { 937bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.put(name, value); 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setName(String name) { 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == null) { 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 946d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyString("Name", name); 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh //TODO(): setPropertyString, setPropertyInteger, setPropertyBoolean 950d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Either have a single property function with Object as the parameter 951d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // or have a function for each property and then obfuscate in the JNI layer. 952d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The following looks dirty. 953d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyString(String key, String value) { 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 9558c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 956d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyStringNative(key, value); 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 959d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyInteger(String key, int value) { 960d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 9618c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 962d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyIntegerNative(key, value); 963d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 965d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyBoolean(String key, boolean value) { 966d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 9678c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 968d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyBooleanNative(key, value ? 1 : 0); 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 971d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /** 972d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Set the discoverability window for the device. A timeout of zero 973d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * makes the device permanently discoverable (if the device is 974d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * discoverable). Setting the timeout to a nonzero value does not make 975d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * a device discoverable; you need to call setMode() to make the device 976d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * explicitly discoverable. 977d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 978d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param timeout_s The discoverable timeout in seconds. 979d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh */ 980d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean setDiscoverableTimeout(int timeout) { 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 983d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyInteger("DiscoverableTimeout", timeout); 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 98612835478ee687a493d1b5882e67b6725bd539c26Nick Pelly public synchronized boolean setScanMode(int mode, int duration) { 98718b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, 98818b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly "Need WRITE_SECURE_SETTINGS permission"); 989de893f550301a60274e87aa8168225e7a7a42184Nick Pelly boolean pairable = false; 990de893f550301a60274e87aa8168225e7a7a42184Nick Pelly boolean discoverable = false; 99112835478ee687a493d1b5882e67b6725bd539c26Nick Pelly 992de893f550301a60274e87aa8168225e7a7a42184Nick Pelly switch (mode) { 993de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 99412835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT); 995d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = false; 996d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 997de893f550301a60274e87aa8168225e7a7a42184Nick Pelly break; 998de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 99912835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT); 1000d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 1001d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 1002005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 1003de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 100412835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT); 1005d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 1006d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = true; 100712835478ee687a493d1b5882e67b6725bd539c26Nick Pelly Message msg = mHandler.obtainMessage(MESSAGE_DISCOVERABLE_TIMEOUT); 100812835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.sendMessageDelayed(msg, duration * 1000); 100912835478ee687a493d1b5882e67b6725bd539c26Nick Pelly if (DBG) Log.d(TAG, "BT Discoverable for " + duration + " seconds"); 1010005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 1011de893f550301a60274e87aa8168225e7a7a42184Nick Pelly default: 1012de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Log.w(TAG, "Requested invalid scan mode " + mode); 1013de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return false; 1014d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1015d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh setPropertyBoolean("Pairable", pairable); 1016d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh setPropertyBoolean("Discoverable", discoverable); 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1018d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return true; 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1021b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh /*package*/ synchronized String getProperty(String name) { 1022b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh if (!isEnabledInternal()) return null; 1023b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh return getPropertyInternal(name); 1024b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh } 1025b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh 1026b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh /*package*/ synchronized String getPropertyInternal(String name) { 1027bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly if (!mAdapterProperties.isEmpty()) 1028bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return mAdapterProperties.get(name); 1029d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh getAllProperties(); 1030bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return mAdapterProperties.get(name); 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1033d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getAddress() { 1034d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1035d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Address"); 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1038d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getName() { 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1040d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Name"); 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1044d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Returns the user-friendly name of a remote device. This value is 1045d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * returned from our local cache, which is updated when onPropertyChange 1046d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * event is received. 1047d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Do not expect to retrieve the updated remote name immediately after 1048d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * changing the name on the remote device. 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1050d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Bluetooth address of remote device. 1051d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 1052d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return The user-friendly name of the specified remote device. 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1054d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getRemoteName(String address) { 1055d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1056005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1057d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1058d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 105955929a958bf0e482c8e4d7df3dd75957f1e9d871Jaikumar Ganesh return getRemoteDeviceProperty(address, "Name"); 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the discoverability window for the device. A timeout of zero 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * means that the device is permanently discoverable (if the device is 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the discoverable mode). 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The discoverability window of the device, in seconds. A negative 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value indicates an error. 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getDiscoverableTimeout() { 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1072d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String timeout = getProperty("DiscoverableTimeout"); 1073d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (timeout != null) 1074d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(timeout); 1075d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 1076d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return -1; 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getScanMode() { 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 10818c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) 1082de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 1083d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1084d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean pairable = getProperty("Pairable").equals("true"); 1085d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean discoverable = getProperty("Discoverable").equals("true"); 1086d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return bluezStringToScanMode (pairable, discoverable); 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean startDiscovery() { 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 10928c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 10938c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1094d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return startDiscoveryNative(); 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1097d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean cancelDiscovery() { 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 11008c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11018c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1102d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return stopDiscoveryNative(); 1103d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1104d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1105d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean isDiscovering() { 1106d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1107d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return mIsDiscovering; 1108d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1109d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1110d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ void setIsDiscovering(boolean isDiscovering) { 1111d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mIsDiscovering = isDiscovering; 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean createBond(String address) { 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 11178c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11188c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1119005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11242092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (mBondState.getPendingOutgoingBonding() != null) { 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project log("Ignoring createBond(): another device is bonding"); 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a different device is currently bonding, fail 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check for bond state only if we are not performing auto 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pairing exponential back-off attempts. 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mBondState.isAutoPairingAttemptsInProgress(address) && 1133005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.getBondState(address) != BluetoothDevice.BOND_NONE) { 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project log("Ignoring createBond(): this device is already bonding or bonded"); 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11383fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (address.equals(mDockAddress)) { 11393fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (!writeDockPin()) { 11403fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("Error while writing Pin for the dock"); 11413fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 11423fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 11433fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 11443fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1145d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!createPairedDeviceNative(address, 60000 /* 1 minute */)) { 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11492092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mBondState.setPendingOutgoingBonding(address); 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); 11512092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean cancelBondProcess(String address) { 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 11588c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11598c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1160005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) { 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1168005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 1170d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh cancelDeviceCreationNative(address); 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean removeBond(String address) { 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 11778c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11788c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1179005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11829b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh BluetoothProfileConnectionState state = mProfileConnectionMgr.get(address); 11839b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 11849b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(BluetoothProfileConnectionState.UNPAIR); 11859b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 11869b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } else { 11879b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 11889b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 11899b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 11909b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 11919b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public synchronized boolean removeBondInternal(String address) { 1192d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return removeDeviceNative(getObjectPathFromAddress(address)); 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized String[] listBonds() { 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.listInState(BluetoothDevice.BOND_BONDED); 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getBondState(String address) { 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1202005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1203b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.getBondState(address.toUpperCase()); 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12083fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh public synchronized boolean isBluetoothDock(String address) { 12096e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 12106e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.MODE_PRIVATE); 12116e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 12126e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh return sp.contains(SHARED_PREFERENCE_DOCK_ADDRESS + address); 12133fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 12143fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 12159488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh /*package*/ boolean isRemoteDeviceInCache(String address) { 1216bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return (mDeviceProperties.get(address) != null); 12179488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 12189488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh 12199488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh /*package*/ String[] getRemoteDeviceProperties(String address) { 12208c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return null; 12218c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 12229488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh String objectPath = getObjectPathFromAddress(address); 12239488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh return (String [])getDevicePropertiesNative(objectPath); 12249488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 12259488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh 1226d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ synchronized String getRemoteDeviceProperty(String address, String property) { 1227bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly Map<String, String> properties = mDeviceProperties.get(address); 1228d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (properties != null) { 1229d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return properties.get(property); 1230d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 1231d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Query for remote device properties, again. 1232d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // We will need to reload the cache when we switch Bluetooth on / off 1233d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // or if we crash. 123410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (updateRemoteDevicePropertiesCache(address)) 1235d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getRemoteDeviceProperty(address, property); 12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1237d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getRemoteDeviceProperty: " + property + "not present:" + address); 1238d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 124110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh /* package */ synchronized boolean updateRemoteDevicePropertiesCache(String address) { 124210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh String[] propValues = getRemoteDeviceProperties(address); 124310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (propValues != null) { 124410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh addRemoteDeviceProperties(address, propValues); 124510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return true; 124610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 124710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return false; 124810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 124910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 1250d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ synchronized void addRemoteDeviceProperties(String address, String[] properties) { 1251395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh /* 1252395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh * We get a DeviceFound signal every time RSSI changes or name changes. 1253395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh * Don't create a new Map object every time */ 1254bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly Map<String, String> propertyValues = mDeviceProperties.get(address); 1255efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh if (propertyValues == null) { 1256395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh propertyValues = new HashMap<String, String>(); 1257395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh } 1258395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh 12598bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int i = 0; i < properties.length; i++) { 12608bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh String name = properties[i]; 1261efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh String newValue = null; 12628bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh int len; 12638bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (name == null) { 12648bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh Log.e(TAG, "Error: Remote Device Property at index" + i + "is null"); 12658bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh continue; 12668bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 12678bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (name.equals("UUIDs") || name.equals("Nodes")) { 1268efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh StringBuilder str = new StringBuilder(); 12698bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh len = Integer.valueOf(properties[++i]); 12708bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int j = 0; j < len; j++) { 1271efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(properties[++i]); 1272efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(","); 1273efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh } 1274efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh if (len > 0) { 1275efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh newValue = str.toString(); 12768bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 1277d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 12788bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh newValue = properties[++i]; 1279d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1280efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh 12818bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh propertyValues.put(name, newValue); 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1283bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties.put(address, propertyValues); 128410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 128510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // We have added a new remote device or updated its properties. 128610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // Also update the serviceChannel cache. 128710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh updateDeviceServiceChannelCache(address); 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1290d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ void removeRemoteDeviceProperties(String address) { 1291bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties.remove(address); 12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1294d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ synchronized void setRemoteDeviceProperty(String address, String name, 1295d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String value) { 1296bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly Map <String, String> propVal = mDeviceProperties.get(address); 1297d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (propVal != null) { 1298d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh propVal.put(name, value); 1299bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties.put(address, propVal); 1300d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 1301d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "setRemoteDeviceProperty for a device not in cache:" + address); 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1306efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Sets the remote device trust state. 1307efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 1308efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * @return boolean to indicate operation success or fail 1309efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1310efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean setTrust(String address, boolean value) { 1311005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1312e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1313e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly "Need BLUETOOTH_ADMIN permission"); 1314efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1315efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1316efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 13178c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13188c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1319efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return setDevicePropertyBooleanNative(getObjectPathFromAddress(address), "Trusted", 1320efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue value ? 1 : 0); 1321efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1322efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1323efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1324efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Gets the remote device trust state as boolean. 1325efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Note: this value may be 1326efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * retrieved from cache if we retrieved the data before * 1327efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 1328efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * @return boolean to indicate trust or untrust state 1329efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1330efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean getTrustState(String address) { 1331005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1332efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1333efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1334efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1335efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1336efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue String val = getRemoteDeviceProperty(address, "Trusted"); 1337efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue if (val == null) { 1338efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1339efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } else { 1340efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return val.equals("true") ? true : false; 1341efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1342efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1343efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1344efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1345d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the remote major, minor classes encoded as a 32-bit 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * integer. 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: this value is retrieved from cache, because we get it during 13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * remote-device discovery. 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return 32-bit integer encoding the remote major, minor, and service 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * classes. 13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getRemoteClass(String address) { 1355005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1356ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1357ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly return BluetoothClass.ERROR; 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1359d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String val = getRemoteDeviceProperty(address, "Class"); 1360d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (val == null) 1361d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return BluetoothClass.ERROR; 1362d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else { 1363d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(val); 1364d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1366d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1369dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * Gets the UUIDs supported by the remote device 13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1371dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @return array of 128bit ParcelUuids 13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1373dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public synchronized ParcelUuid[] getRemoteUuids(String address) { 13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1375005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13781caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return getUuidFromCache(address); 13791caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 13801caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 13811caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private ParcelUuid[] getUuidFromCache(String address) { 1382d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String value = getRemoteDeviceProperty(address, "UUIDs"); 1383dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh if (value == null) return null; 1384dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1385dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh String[] uuidStrings = null; 1386d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The UUIDs are stored as a "," separated string. 1387dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuidStrings = value.split(","); 1388dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; 1389dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1390dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh for (int i = 0; i < uuidStrings.length; i++) { 1391dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuids[i] = ParcelUuid.fromString(uuidStrings[i]); 1392dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh } 1393d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return uuids; 13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 139616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** 139716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Connect and fetch new UUID's using SDP. 139816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * The UUID's found are broadcast as intents. 139916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Optionally takes a uuid and callback to fetch the RFCOMM channel for the 140016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * a given uuid. 140116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to broadcast UUID intents on success 140216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to handle the failure case for 140316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * callback and broadcast intents. 140416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly */ 140516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public synchronized boolean fetchRemoteUuids(String address, ParcelUuid uuid, 140616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback) { 14071caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 14088c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 14098c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 14101caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (!BluetoothAdapter.checkBluetoothAddress(address)) { 14111caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return false; 14121caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 14131caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 141416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = new RemoteService(address, uuid); 141516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null && mUuidCallbackTracker.get(service) != null) { 141616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // An SDP query for this address & uuid is already in progress 141716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Do not add this callback for the uuid 141816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 141916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 142016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 14211caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (mUuidIntentTracker.contains(address)) { 14221caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // An SDP query for this address is already in progress 142316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Add this uuid onto the in-progress SDP query 142416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 142516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 142616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 14271caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return true; 14281caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 14291caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 14301caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh boolean ret; 14310e09030977aea8b40fd177139528d4b5637c9771Jaikumar Ganesh // Just do the SDP if the device is already created and UUIDs are not 14320e09030977aea8b40fd177139528d4b5637c9771Jaikumar Ganesh // NULL, else create the device and then do SDP. 14330e09030977aea8b40fd177139528d4b5637c9771Jaikumar Ganesh if (isRemoteDeviceInCache(address) && getRemoteUuids(address) != null) { 14341caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String path = getObjectPathFromAddress(address); 14351caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (path == null) return false; 14361caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 14371caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // Use an empty string for the UUID pattern 14381caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh ret = discoverServicesNative(path, ""); 14391caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } else { 14401caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh ret = createDeviceNative(address); 14411caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 14421caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 14431caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker.add(address); 144416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 144516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 144616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 14471caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 14481caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT); 14491caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh message.obj = address; 14501caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY); 14511caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return ret; 14521caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 14531caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1455d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the rfcomm channel associated with the UUID. 145616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Pulls records from the cache only. 14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1458d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Address of the remote device 1459dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @param uuid ParcelUuid of the service attribute 14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1461d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return rfcomm channel associated with the service attribute 146210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh * -1 on error 14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1464dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public int getRemoteServiceChannel(String address, ParcelUuid uuid) { 14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 14668c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 14678c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1468005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1469b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 147110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // Check if we are recovering from a crash. 147210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (mDeviceProperties.isEmpty()) { 147310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (!updateRemoteDevicePropertiesCache(address)) 147410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 147510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 147610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 147710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address); 147810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (value != null && value.containsKey(uuid)) 147910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return value.get(uuid); 148010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setPin(String address, byte[] pin) { 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 14868c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 14878c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pin == null || pin.length <= 0 || pin.length > 16 || 1489005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly !BluetoothAdapter.checkBluetoothAddress(address)) { 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "setPin(" + address + ") called but no native data available, " + 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " or by bluez.\n"); 14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bluez API wants pin as a string 15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pinString; 15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pinString = new String(pin, "UTF8"); 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (UnsupportedEncodingException uee) { 15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "UTF8 not supported?!?"); 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return setPinNative(address, pinString, data.intValue()); 15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1511b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPasskey(String address, int passkey) { 1512b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1513b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 15148c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 15158c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1516005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (passkey < 0 || passkey > 999999 || !BluetoothAdapter.checkBluetoothAddress(address)) { 1517b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1518b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1519b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1520b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1521b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1522b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1523b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1524b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1525b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1526b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1527b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPasskeyNative(address, passkey, data.intValue()); 1528b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1529b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1530b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPairingConfirmation(String address, boolean confirm) { 1531b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1532b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 15338c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 15348c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1535b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1536b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1537b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1538b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1539b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1540b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1541b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1542b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1543b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPairingConfirmationNative(address, confirm, data.intValue()); 1544b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1545b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1546b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean cancelPairingUserInput(String address) { 15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 15498c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 15508c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1551005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1554005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 1555397d8f4f4829a45f4fe7a672cc395466bbc0f442Jaikumar Ganesh BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 1559b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "cancelUserInputNative(" + address + ") called but no native data " + 1560b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "available, ignoring. Maybe the PasskeyAgent Request was already cancelled " + 1561b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "by the remote or by bluez.\n"); 15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1564b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return cancelPairingUserInputNative(address, data.intValue()); 15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15678c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh /*package*/ void updateDeviceServiceChannelCache(String address) { 156810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh ParcelUuid[] deviceUuids = getRemoteUuids(address); 156910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // We are storing the rfcomm channel numbers only for the uuids 157010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // we are interested in. 157110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh int channel; 157216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("updateDeviceServiceChannelCache(" + address + ")"); 157316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 157416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly ArrayList<ParcelUuid> applicationUuids = new ArrayList(); 157516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 157616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 157716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (RemoteService service : mUuidCallbackTracker.keySet()) { 157816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 157916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly applicationUuids.add(service.uuid); 158016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 158116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 158216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 158310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 158410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh Map <ParcelUuid, Integer> value = new HashMap<ParcelUuid, Integer>(); 158516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 158616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for default uuids 158716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : RFCOMM_UUIDS) { 158810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 158916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = getDeviceServiceChannelNative(getObjectPathFromAddress(address), 159016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly uuid.toString(), 0x0004); 159116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("\tuuid(system): " + uuid + " " + channel); 159210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh value.put(uuid, channel); 159310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 159410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 159516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for application requested uuids 159616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : applicationUuids) { 159716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 159816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = getDeviceServiceChannelNative(getObjectPathFromAddress(address), 159916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly uuid.toString(), 0x0004); 160016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("\tuuid(application): " + uuid + " " + channel); 160116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly value.put(uuid, channel); 160216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 160316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 160416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 160516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 160616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Make application callbacks 160716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 160816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 160916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 161016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 161116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = -1; 161216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (value.get(service.uuid) != null) { 161316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = value.get(service.uuid); 161416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 161516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (channel != -1) { 161616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("Making callback for " + service.uuid + " with result " + 161716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel); 161816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 161916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 162016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 162116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(channel); 162216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 162316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 162416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 162516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 162616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 162716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 162816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 162916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 163016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Update cache 163116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mDeviceServiceChannelCache.put(address, value); 163216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 163310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 163410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 163524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly /** 163624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * b is a handle to a Binder instance, so that this service can be notified 163724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * for Applications that terminate unexpectedly, to clean there service 163824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * records 163924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly */ 164024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid, 164124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int channel, IBinder b) { 16428c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 16438c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 16448c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 164524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (serviceName == null || uuid == null || channel < 1 || 164624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) { 164724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 164824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 164924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) { 165024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Log.w(TAG, "Attempted to register a reserved UUID: " + uuid); 165124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 165224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 165324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle = addRfcommServiceRecordNative(serviceName, 165424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(), 165524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly (short)channel); 165624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (DBG) log("new handle " + Integer.toHexString(handle)); 165724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (handle == -1) { 165824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 165924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 166024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 166124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int pid = Binder.getCallingPid(); 166224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.put(new Integer(handle), new Integer(pid)); 166324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly try { 166424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly b.linkToDeath(new Reaper(handle, pid), 0); 166524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } catch (RemoteException e) {} 166624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return handle; 166724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 166824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 166924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void removeServiceRecord(int handle) { 167024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 167124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly "Need BLUETOOTH permission"); 167224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly checkAndRemoveRecord(handle, Binder.getCallingPid()); 167324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 167424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 167524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private synchronized void checkAndRemoveRecord(int handle, int pid) { 167624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer handleInt = new Integer(handle); 167724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer owner = mServiceRecordToPid.get(handleInt); 167824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (owner != null && pid == owner.intValue()) { 167924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (DBG) log("Removing service record " + Integer.toHexString(handle) + " for pid " + 168024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pid); 168124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.remove(handleInt); 168224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly removeServiceRecordNative(handle); 168324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 168424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 168524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 168624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private class Reaper implements IBinder.DeathRecipient { 168724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int pid; 168824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle; 168924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Reaper(int handle, int pid) { 169024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly this.pid = pid; 169124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly this.handle = handle; 169224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 169324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void binderDied() { 169424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly synchronized (BluetoothService.this) { 169524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (DBG) log("Tracked app " + pid + " died"); 169624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly checkAndRemoveRecord(handle, pid); 169724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 169824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 169924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 170024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 17046e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (intent == null) return; 17056e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String action = intent.getAction(); 17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver resolver = context.getContentResolver(); 17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Query the airplane mode from Settings.System just to make sure that 17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // some random app is not sending this intent and disabling bluetooth 17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean enabled = !isAirplaneModeOn(); 17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If bluetooth is currently expected to be on, then enable or disable bluetooth 17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) { 17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (enabled) { 1715105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project enable(false); 17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project disable(false); 17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17206e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else if (Intent.ACTION_DOCK_EVENT.equals(action)) { 17216e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 17226e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh Intent.EXTRA_DOCK_STATE_UNDOCKED); 17236e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (DBG) Log.v(TAG, "Received ACTION_DOCK_EVENT with State:" + state); 17246e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) { 17256e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockAddress = null; 17266e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockPin = null; 17276e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else { 17286e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences.Editor editor = 17296e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 17306e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.MODE_PRIVATE).edit(); 17316e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh editor.putBoolean(SHARED_PREFERENCE_DOCK_ADDRESS + mDockAddress, true); 17326e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh editor.commit(); 17336e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } 17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17386e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private void registerForAirplaneMode(IntentFilter filter) { 173944303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final ContentResolver resolver = mContext.getContentResolver(); 174044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String airplaneModeRadios = Settings.System.getString(resolver, 17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_RADIOS); 174244303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String toggleableRadios = Settings.System.getString(resolver, 174344303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 174444303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 174544303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneSensitive = airplaneModeRadios == null ? true : 174644303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH); 174744303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneToggleable = toggleableRadios == null ? false : 174844303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH); 174944303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsAirplaneSensitive) { 17516e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Returns true if airplane mode is currently on */ 17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean isAirplaneModeOn() { 17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Settings.System.getInt(mContext.getContentResolver(), 17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_ON, 0) == 1; 17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17611caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /* Broadcast the Uuid intent */ 17621caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /*package*/ synchronized void sendUuidIntent(String address) { 17636179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh ParcelUuid[] uuid = getUuidFromCache(address); 17646179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_UUID); 17652d3b98d868cda30535505b2a2fba47aa1c9c052bJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 17666179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid); 17676179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 17681caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 17696179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh if (mUuidIntentTracker.contains(address)) 17701caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker.remove(address); 177116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 177216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 177316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 177416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ synchronized void makeServiceChannelCallbacks(String address) { 177516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 177616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 177716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 177816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 177916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("Cleaning up failed UUID channel lookup: " + service.address + 178016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly " " + service.uuid); 178116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 178216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 178316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 178416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(-1); 178516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 178616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 178716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 178816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 178916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 179016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 17911caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 17921caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1795105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project switch(mBluetoothState) { 1796de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_OFF: 179724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth OFF\n"); 1798105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1799de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_TURNING_ON: 180024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth TURNING ON\n"); 1801105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1802de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_TURNING_OFF: 180324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth TURNING OFF\n"); 1804105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1805de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_ON: 180624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth ON\n"); 1807105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1808105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 180924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive); 181044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey pw.println("mIsAirplaneToggleable = " + mIsAirplaneToggleable); 181124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 181224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local address = " + getAddress()); 181324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local name = " + getName()); 181424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("isDiscovering() = " + isDiscovering()); 1815105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1816105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BluetoothHeadset headset = new BluetoothHeadset(mContext, null); 1817105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1818105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--Known devices--"); 1819bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly for (String address : mDeviceProperties.keySet()) { 18201eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly int bondState = mBondState.getBondState(address); 1821105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.printf("%s %10s (%d) %s\n", address, 18221eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly toBondStateString(bondState), 1823105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBondState.getAttempt(address), 1824105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project getRemoteName(address)); 182524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 182624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Map<ParcelUuid, Integer> uuidChannels = mDeviceServiceChannelCache.get(address); 182724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (uuidChannels == null) { 182824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\tuuids = null"); 182924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } else { 183024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly for (ParcelUuid uuid : uuidChannels.keySet()) { 183124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer channel = uuidChannels.get(uuid); 183224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (channel == null) { 183324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\t" + uuid); 183424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } else { 183524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\t" + uuid + " RFCOMM channel = " + channel); 18361eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly } 18371eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly } 18381eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly } 183916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (RemoteService service : mUuidCallbackTracker.keySet()) { 184016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 184116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly pw.println("\tPENDING CALLBACK: " + service.uuid); 184216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 184316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 1844105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1845105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1846d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String value = getProperty("Devices"); 18471eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly String[] devicesObjectPath = null; 1848d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (value != null) { 1849d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh devicesObjectPath = value.split(","); 1850d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1851105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--ACL connected devices--"); 185224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (devicesObjectPath != null) { 185324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly for (String device : devicesObjectPath) { 185424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println(getAddressFromObjectPath(device)); 185524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 1856105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1857105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1858105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Rather not do this from here, but no-where else and I need this 1859105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // dump 1860105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--Headset Service--"); 1861740e39be6af3e366a4b82c030b5ea67ab144b42aJaikumar Ganesh switch (headset.getState(headset.getCurrentHeadset())) { 1862105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_DISCONNECTED: 1863105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_DISCONNECTED"); 1864105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 1865105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_CONNECTING: 1866105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_CONNECTING"); 1867105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 1868105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_CONNECTED: 1869105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_CONNECTED"); 1870105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 1871105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_ERROR: 1872105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_ERROR"); 1873105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 1874105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 18756c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly 187624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\ngetCurrentHeadset() = " + headset.getCurrentHeadset()); 187724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("getBatteryUsageHint() = " + headset.getBatteryUsageHint()); 1878105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project headset.close(); 187924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\n--Application Service Records--"); 188024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly for (Integer handle : mServiceRecordToPid.keySet()) { 188124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer pid = mServiceRecordToPid.get(handle); 188224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle)); 188324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1886d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) { 1887d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (pairable && discoverable) 1888bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1889d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else if (pairable && !discoverable) 1890bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 1891d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 1892bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static String scanModeToBluezString(int mode) { 18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mode) { 1897bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "off"; 1899bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "connectable"; 1901bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "discoverable"; 19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1907d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getAddressFromObjectPath(String objectPath) { 1908b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh String adapterObjectPath = getPropertyInternal("ObjectPath"); 1909d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (adapterObjectPath == null || objectPath == null) { 1910d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: AdpaterObjectPath:" + adapterObjectPath + 1911d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " or deviceObjectPath:" + objectPath + " is null"); 1912d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1913d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1914d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!objectPath.startsWith(adapterObjectPath)) { 1915d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: AdpaterObjectPath:" + adapterObjectPath + 1916d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " is not a prefix of deviceObjectPath:" + objectPath + 1917d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh "bluetoothd crashed ?"); 1918d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1919d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1920d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String address = objectPath.substring(adapterObjectPath.length()); 1921d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (address != null) return address.replace('_', ':'); 1922d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1923d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: Address being returned is null"); 1924d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1925d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1926d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1927d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getObjectPathFromAddress(String address) { 1928b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh String path = getPropertyInternal("ObjectPath"); 1929d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (path == null) { 1930d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "Error: Object Path is null"); 1931d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1932d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1933d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh path = path + address.replace(":", "_"); 1934d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return path; 1935d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1936d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1937b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh /*package */ void setLinkTimeout(String address, int num_slots) { 1938b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh String path = getObjectPathFromAddress(address); 1939b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh boolean result = setLinkTimeoutNative(path, num_slots); 1940b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 1941b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh if (!result) log("Set Link Timeout to:" + num_slots + " slots failed"); 1942b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh } 1943b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 19449b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectHeadset(String address) { 19459b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh BluetoothProfileConnectionState state = mProfileConnectionMgr.get(address); 19469b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 19479b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(BluetoothProfileConnectionState.CONNECT_HFP_OUTGOING); 19489b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 19499b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 19509b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 19519b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 19529b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 19539b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectHeadset(String address) { 19549b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh BluetoothProfileConnectionState state = mProfileConnectionMgr.get(address); 19559b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 19569b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(BluetoothProfileConnectionState.DISCONNECT_HFP_OUTGOING); 19579b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 19589b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 19599b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 19609b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 19619b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 19629b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectSink(String address) { 19639b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh BluetoothProfileConnectionState state = mProfileConnectionMgr.get(address); 19649b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 19659b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(BluetoothProfileConnectionState.CONNECT_A2DP_OUTGOING); 19669b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 19679b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 19689b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 19699b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 19709b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 19719b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectSink(String address) { 19729b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh BluetoothProfileConnectionState state = mProfileConnectionMgr.get(address); 19739b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 19749b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(BluetoothProfileConnectionState.DISCONNECT_A2DP_OUTGOING); 19759b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 19769b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 19779b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 19789b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 19799b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 19809b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private BluetoothProfileConnectionState addProfileState(String address) { 19819b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh BluetoothProfileConnectionState state = mProfileConnectionMgr.get(address); 19829b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) return state; 19839b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 19849b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state = new BluetoothProfileConnectionState(mContext, address, this, mA2dpService); 19859b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh mProfileConnectionMgr.put(address, state); 19869b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.start(); 19879b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return state; 19889b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 19899b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 19909b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private void removeProfileState(String address) { 19919b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh mProfileConnectionMgr.remove(address); 19929b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 19939b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 19949b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private void initProfileState() { 19959b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh String []bonds = null; 19969b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh String val = getPropertyInternal("Devices"); 19979b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (val != null) { 19989b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh bonds = val.split(","); 19999b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20009b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (bonds == null) { 20019b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return; 20029b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20039b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 20049b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh for (String path : bonds) { 20059b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh String address = getAddressFromObjectPath(path); 20069b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh BluetoothProfileConnectionState state = addProfileState(address); 20079b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh // Allow 8 secs for SDP records to get registered. 20089b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 20099b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh msg.what = BluetoothProfileConnectionState.AUTO_CONNECT_PROFILES; 20109b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessageDelayed(msg, 8000); 20119b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20129b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20139b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 20149b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean notifyIncomingConnection(String address) { 20159b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh BluetoothProfileConnectionState state = 20169b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh mProfileConnectionMgr.get(address); 20179b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 20189b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 20199b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh msg.what = BluetoothProfileConnectionState.CONNECT_HFP_INCOMING; 20209b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(msg); 20219b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 20229b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20239b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 20249b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20259b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 20269b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /*package*/ boolean notifyIncomingA2dpConnection(String address) { 20279b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh BluetoothProfileConnectionState state = 20289b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh mProfileConnectionMgr.get(address); 20299b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 20309b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 20319b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh msg.what = BluetoothProfileConnectionState.CONNECT_A2DP_INCOMING; 20329b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(msg); 20339b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 20349b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20359b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 20369b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20379b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 20389b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /*package*/ void setA2dpService(BluetoothA2dpService a2dpService) { 20399b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh mA2dpService = a2dpService; 20409b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20419b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 20429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void log(String msg) { 20439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, msg); 20449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2045d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2046d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native static void classInitNative(); 2047d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void initializeNativeDataNative(); 2048d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setupNativeDataNative(); 2049d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean tearDownNativeDataNative(); 2050d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void cleanupNativeDataNative(); 2051d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native String getAdapterPathNative(); 2052d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2053d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int isEnabledNative(); 2054d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int enableNative(); 2055d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int disableNative(); 2056d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2057d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native Object[] getAdapterPropertiesNative(); 2058d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native Object[] getDevicePropertiesNative(String objectPath); 2059d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyStringNative(String key, String value); 2060d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyIntegerNative(String key, int value); 2061d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyBooleanNative(String key, int value); 2062d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2063d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean startDiscoveryNative(); 2064d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean stopDiscoveryNative(); 2065d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2066d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean createPairedDeviceNative(String address, int timeout_ms); 2067d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean cancelDeviceCreationNative(String address); 2068d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean removeDeviceNative(String objectPath); 2069d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int getDeviceServiceChannelNative(String objectPath, String uuid, 2070d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh int attributeId); 2071d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2072b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean cancelPairingUserInputNative(String address, int nativeData); 2073d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setPinNative(String address, String pin, int nativeData); 2074b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPasskeyNative(String address, int passkey, int nativeData); 2075b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPairingConfirmationNative(String address, boolean confirm, 2076b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh int nativeData); 207724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean setDevicePropertyBooleanNative(String objectPath, String key, 207824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int value); 20791caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private native boolean createDeviceNative(String address); 208016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ native boolean discoverServicesNative(String objectPath, String pattern); 208110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 208224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb, 208324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly short channel); 208424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean removeServiceRecordNative(int handle); 2085b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh private native boolean setLinkTimeoutNative(String path, int num_slots); 20869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2087