BluetoothService.java revision 05a1863cebcc8e318283f3f4a49ba69d83b62866
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 27545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.bluetooth.BluetoothA2dp; 28bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.BluetoothAdapter; 29dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganeshimport android.bluetooth.BluetoothClass; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothDevice; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothHeadset; 32f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganeshimport android.bluetooth.BluetoothDeviceProfileState; 33f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganeshimport android.bluetooth.BluetoothProfileState; 34545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.bluetooth.BluetoothInputDevice; 3524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pellyimport android.bluetooth.BluetoothSocket; 3610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganeshimport android.bluetooth.BluetoothUuid; 37bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.IBluetooth; 3816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport android.bluetooth.IBluetoothCallback; 39545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.bluetooth.IBluetoothHeadset; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 456e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganeshimport android.content.SharedPreferences; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 483fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.IBinder; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 503fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.ParcelUuid; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 52105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.os.ServiceManager; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemService; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 57d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganeshimport com.android.internal.app.IBatteryStats; 58d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedInputStream; 60c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganeshimport java.io.BufferedReader; 613fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedWriter; 62c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganeshimport java.io.DataInputStream; 63c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganeshimport java.io.File; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileInputStream; 663fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileNotFoundException; 67c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganeshimport java.io.FileOutputStream; 683fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileWriter; 693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.IOException; 70c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganeshimport java.io.InputStreamReader; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.UnsupportedEncodingException; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 76545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport java.util.HashSet; 7716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport java.util.Iterator; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 79545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport java.util.Set; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 81bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellypublic class BluetoothService extends IBluetooth.Stub { 82bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private static final String TAG = "BluetoothService"; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean DBG = true; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNativeData; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BluetoothEventLoop mEventLoop; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsAirplaneSensitive; 8844303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey private boolean mIsAirplaneToggleable; 89105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private int mBluetoothState; 90997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly private boolean mRestart = false; // need to call enable() after disable() 91bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private boolean mIsDiscovering; 92997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 93bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private BluetoothAdapter mAdapter; // constant after init() 94997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly private final BondState mBondState = new BondState(); // local cache of bondings 95105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private final IBatteryStats mBatteryStats; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1013fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_ADDRESS_PATH = "/sys/class/switch/dock/bt_addr"; 1023fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_PIN_PATH = "/sys/class/switch/dock/bt_pin"; 1033fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1046e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address"; 1056e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings"; 1066e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 107105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static final int MESSAGE_REGISTER_SDP_RECORDS = 1; 108105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static final int MESSAGE_FINISH_DISABLE = 2; 1091caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private static final int MESSAGE_UUID_INTENT = 3; 11012835478ee687a493d1b5882e67b6725bd539c26Nick Pelly private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 4; 1111caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 1121caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // The timeout used to sent the UUIDs Intent 1131caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // This timeout should be greater than the page timeout 1141caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private static final int UUID_INTENT_DELAY = 6000; 115105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 11616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** Always retrieve RFCOMM channel for these SDP UUIDs */ 11716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static final ParcelUuid[] RFCOMM_UUIDS = { 11816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.Handsfree, 11916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.HSP, 12016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.ObexObjectPush }; 12116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1229b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh // TODO(): Optimize all these string handling 123bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private final Map<String, String> mAdapterProperties; 12416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<String, Map<String, String>> mDeviceProperties; 125d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 12616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache; 12716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final ArrayList<String> mUuidIntentTracker; 12816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker; 1291caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 13024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private final HashMap<Integer, Integer> mServiceRecordToPid; 13124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 132f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState; 133f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final BluetoothProfileState mA2dpProfileState; 134f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final BluetoothProfileState mHfpProfileState; 135de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh private final BluetoothProfileState mHidProfileState; 1369b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 1379b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private BluetoothA2dpService mA2dpService; 138545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh private final HashMap<BluetoothDevice, Integer> mInputDevices; 139545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1403fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static String mDockAddress; 1413fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private String mDockPin; 1423fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 14316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static class RemoteService { 14416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public String address; 14516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public ParcelUuid uuid; 14616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public RemoteService(String address, ParcelUuid uuid) { 14716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.address = address; 14816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.uuid = uuid; 14916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 15016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly @Override 15116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public boolean equals(Object o) { 15216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (o instanceof RemoteService) { 15316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = (RemoteService)o; 15416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return address.equals(service.address) && uuid.equals(service.uuid); 15516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 15616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 15716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 1585f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root 1595f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root @Override 1605f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root public int hashCode() { 1615f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root int hash = 1; 1625f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (address == null ? 0 : address.hashCode()); 1635f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (uuid == null ? 0 : uuid.hashCode()); 1645f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root return hash; 1655f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root } 16616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 16716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project classInitNative(); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 172bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public BluetoothService(Context context) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 174105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 175105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Need to do this in place of: 176105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // mBatteryStats = BatteryStatsService.getService(); 177105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Since we can not import BatteryStatsService from here. This class really needs to be 178105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // moved to java/services/com/android/server/ 179105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initializeNativeDataNative(); 182ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 183ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (isEnabledNative() == 1) { 184ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Log.w(TAG, "Bluetooth daemons already running - runtime restart? "); 185ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project disableNative(); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 187ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 188de893f550301a60274e87aa8168225e7a7a42184Nick Pelly mBluetoothState = BluetoothAdapter.STATE_OFF; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsDiscovering = false; 190bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties = new HashMap<String, String>(); 191bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties = new HashMap<String, Map<String,String>>(); 19210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 19310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>(); 1941caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker = new ArrayList<String>(); 19516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>(); 19624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid = new HashMap<Integer, Integer>(); 197f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>(); 198f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP); 199f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP); 200de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh mHidProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HID); 201f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh 202f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.start(); 203f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.start(); 204de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh mHidProfileState.start(); 2053fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2063fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh IntentFilter filter = new IntentFilter(); 2076e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh registerForAirplaneMode(filter); 2086e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 2093fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh filter.addAction(Intent.ACTION_DOCK_EVENT); 2106e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.registerReceiver(mReceiver, filter); 211545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh mInputDevices = new HashMap<BluetoothDevice, Integer>(); 2123fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2133fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2149b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public static synchronized String readDockBluetoothAddress() { 2153fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (mDockAddress != null) return mDockAddress; 2163fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2173fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedInputStream file = null; 2183fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh String dockAddress; 2193fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2203fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file = new BufferedInputStream(new FileInputStream(DOCK_ADDRESS_PATH)); 2213fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh byte[] address = new byte[17]; 2223fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.read(address); 2233fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = new String(address); 2243fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = dockAddress.toUpperCase(); 2253fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (BluetoothAdapter.checkBluetoothAddress(dockAddress)) { 2263fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = dockAddress; 2273fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockAddress; 2283fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } else { 2293fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("CheckBluetoothAddress failed for car dock address:" + dockAddress); 2303fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2313fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2323fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("FileNotFoundException while trying to read dock address"); 2333fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2343fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("IOException while trying to read dock address"); 2353fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 2363fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (file != null) { 2373fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2383fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.close(); 2393fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2403fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 2413fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2423fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2433fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2443fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = null; 2453fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return null; 2463fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2473fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2483fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private synchronized boolean writeDockPin() { 2493fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedWriter out = null; 2503fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2513fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out = new BufferedWriter(new FileWriter(DOCK_PIN_PATH)); 2523fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2533fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Generate a random 4 digit pin between 0000 and 9999 2543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // This is not truly random but good enough for our purposes. 2553fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh int pin = (int) Math.floor(Math.random() * 10000); 2563fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2573fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = String.format("%04d", pin); 2583fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.write(mDockPin); 2593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return true; 2603fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2613fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("FileNotFoundException while trying to write dock pairing pin"); 2623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2633fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("IOException while while trying to write dock pairing pin"); 2643fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 2653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (out != null) { 2663fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2673fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.close(); 2683fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 2703fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2713fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2723fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2733fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = null; 2743fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 2753fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2763fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2773fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh /*package*/ synchronized String getDockPin() { 2783fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockPin; 279bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly } 280bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly 281bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public synchronized void initAfterRegistration() { 282f242b7b931898856bcbcb7ec36cacf43098ba544Nick Pelly mAdapter = BluetoothAdapter.getDefaultAdapter(); 283bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mEventLoop = new BluetoothEventLoop(mContext, mAdapter, this); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 2886e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.unregisterReceiver(mReceiver); 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cleanupNativeDataNative(); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isEnabled() { 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2988c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh return isEnabledInternal(); 2998c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh } 3008c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 3018c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh private boolean isEnabledInternal() { 302de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return mBluetoothState == BluetoothAdapter.STATE_ON; 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 305105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public int getBluetoothState() { 306105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 307105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return mBluetoothState; 308105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 309105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 310105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth and disable BT in settings. Returns true on success. 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean disable() { 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return disable(true); 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth. Returns true on success. 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 321e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly * @param saveSetting If true, persist the new setting 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean disable(boolean saveSetting) { 324e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 326105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project switch (mBluetoothState) { 327de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_OFF: 328105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 329de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_ON: 330105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 331105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project default: 332105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return false; 333105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEnableThread != null && mEnableThread.isAlive()) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 337de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF); 338bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.removeMessages(MESSAGE_REGISTER_SDP_RECORDS); 339105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 340105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Allow 3 seconds for profiles to gracefully disconnect 341105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // TODO: Introduce a callback mechanism so that each profile can notify 342bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly // BluetoothService when it is done shutting down 343105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mHandler.sendMessageDelayed( 344105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000); 345105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 346105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 347105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 348105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 349105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private synchronized void finishDisable(boolean saveSetting) { 350de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_TURNING_OFF) { 351105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEventLoop.stop(); 354d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh tearDownNativeDataNative(); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project disableNative(); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mark in progress bondings as cancelled 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) { 359005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // update mode 364de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 365de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE); 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 368105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mIsDiscovering = false; 369bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.clear(); 37024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.clear(); 371105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (saveSetting) { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project persistBluetoothOnSetting(false); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 375105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 376de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_OFF); 377105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 378105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Log bluetooth off to battery stats. 379105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project long ident = Binder.clearCallingIdentity(); 380105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project try { 381105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats.noteBluetoothOff(); 382105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } catch (RemoteException e) { 383105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } finally { 384105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Binder.restoreCallingIdentity(ident); 385105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 386997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 387997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (mRestart) { 388997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 389997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly enable(); 390997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 393105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /** Bring up BT and persist BT on in settings */ 394105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public boolean enable() { 395105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return enable(true); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enable this Bluetooth device, asynchronously. 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This turns on/off the underlying hardware. 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 402105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @param saveSetting If true, persist the new state of BT in settings 403105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @return True on success (so far) 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 405105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public synchronized boolean enable(boolean saveSetting) { 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Airplane mode can prevent Bluetooth radio from being turned on. 41044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 413de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_OFF) { 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEnableThread != null && mEnableThread.isAlive()) { 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 419de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_TURNING_ON); 420105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mEnableThread = new EnableThread(saveSetting); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEnableThread.start(); 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 425997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /** Forcibly restart Bluetooth if it is on */ 426997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /* package */ synchronized void restart() { 427de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_ON) { 428997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly return; 429997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 430997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = true; 431997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (!disable(false)) { 432997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 433997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 434d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 435997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 436105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private synchronized void setBluetoothState(int state) { 437105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (state == mBluetoothState) { 438105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 439105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 440105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 441105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (DBG) log("Bluetooth state " + mBluetoothState + " -> " + state); 442105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 443de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 444de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mBluetoothState); 445de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_STATE, state); 446105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 447105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 448105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBluetoothState = state; 449105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 450105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 451105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 452105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Handler mHandler = new Handler() { 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 457105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case MESSAGE_REGISTER_SDP_RECORDS: 4588c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) { 459bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly return; 460bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly } 461bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // SystemService.start() forks sdptool to register service 462bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // records. It can fail to register some records if it is 463bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // forked multiple times in a row, probably because there is 464bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // some race in sdptool or bluez when operated in parallel. 465bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // As a workaround, delay 500ms between each fork of sdptool. 466bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // TODO: Don't fork sdptool in order to regsiter service 467bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // records, use a DBUS call instead. 468bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly switch (msg.arg1) { 469bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 1: 47077b4ad0e496941a28382eb938a05831f1f8d2d4aJaikumar Ganesh Log.d(TAG, "Registering hfag record"); 47177b4ad0e496941a28382eb938a05831f1f8d2d4aJaikumar Ganesh SystemService.start("hfag"); 472bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 473bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 2, -1), 500); 474bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 475bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 2: 47677b4ad0e496941a28382eb938a05831f1f8d2d4aJaikumar Ganesh Log.d(TAG, "Registering hsag record"); 47777b4ad0e496941a28382eb938a05831f1f8d2d4aJaikumar Ganesh SystemService.start("hsag"); 478bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 479bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 3, -1), 500); 480bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 481bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 3: 482bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly Log.d(TAG, "Registering opush record"); 48303c707ab6fc97e99b1603b8d6edc604dbea3cd6fNick Pelly SystemService.start("opush"); 484bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 485bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 4, -1), 500); 486bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 487bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 4: 488bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly Log.d(TAG, "Registering pbap record"); 48967542964876aa7e4216e8f69f21dda68e7463b9aJaikumar Ganesh SystemService.start("pbap"); 490bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 492105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 493105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case MESSAGE_FINISH_DISABLE: 494105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project finishDisable(msg.arg1 != 0); 495105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 4961caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh case MESSAGE_UUID_INTENT: 4971caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String address = (String)msg.obj; 49816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (address != null) { 4991caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh sendUuidIntent(address); 50016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly makeServiceChannelCallbacks(address); 50116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 5021caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh break; 50312835478ee687a493d1b5882e67b6725bd539c26Nick Pelly case MESSAGE_DISCOVERABLE_TIMEOUT: 50412835478ee687a493d1b5882e67b6725bd539c26Nick Pelly int mode = msg.arg1; 5058c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (isEnabledInternal()) { 50612835478ee687a493d1b5882e67b6725bd539c26Nick Pelly // TODO: Switch back to the previous scan mode 50712835478ee687a493d1b5882e67b6725bd539c26Nick Pelly // This is ok for now, because we only use 50812835478ee687a493d1b5882e67b6725bd539c26Nick Pelly // CONNECTABLE and CONNECTABLE_DISCOVERABLE 50912835478ee687a493d1b5882e67b6725bd539c26Nick Pelly setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, -1); 51012835478ee687a493d1b5882e67b6725bd539c26Nick Pelly } 51112835478ee687a493d1b5882e67b6725bd539c26Nick Pelly break; 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private EnableThread mEnableThread; 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class EnableThread extends Thread { 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean mSaveSetting; 520105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public EnableThread(boolean saveSetting) { 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSaveSetting = saveSetting; 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean res = (enableNative() == 0); 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res) { 526b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project int retryCount = 2; 527b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project boolean running = false; 528b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project while ((retryCount-- > 0) && !running) { 529b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mEventLoop.start(); 530105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // it may take a momement for the other thread to do its 531b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // thing. Check periodically for a while. 532b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project int pollCount = 5; 533b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project while ((pollCount-- > 0) && !running) { 534b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (mEventLoop.isEventLoopRunning()) { 535b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project running = true; 536b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project break; 537b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 538b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project try { 539b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project Thread.sleep(100); 540b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } catch (InterruptedException e) {} 541b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 542b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 543b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (!running) { 544b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project log("bt EnableThread giving up"); 545b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project res = false; 546b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project disableNative(); 547b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res) { 552d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!setupNativeDataNative()) { 553d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return; 554d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSaveSetting) { 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project persistBluetoothOnSetting(true); 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsDiscovering = false; 559c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mBondState.readAutoPairingData(); 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.loadBondState(); 5619b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh initProfileState(); 562bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 563bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 1, -1), 3000); 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 565105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Log bluetooth on to battery stats. 566105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project long ident = Binder.clearCallingIdentity(); 567105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project try { 568105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats.noteBluetoothOn(); 569105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } catch (RemoteException e) { 570105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } finally { 571105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Binder.restoreCallingIdentity(ident); 572105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 574105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 575105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mEnableThread = null; 576105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 577105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project setBluetoothState(res ? 578de893f550301a60274e87aa8168225e7a7a42184Nick Pelly BluetoothAdapter.STATE_ON : 579de893f550301a60274e87aa8168225e7a7a42184Nick Pelly BluetoothAdapter.STATE_OFF); 580105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 581b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (res) { 582105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Update mode 583d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String[] propVal = {"Pairable", getProperty("Pairable")}; 584d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mEventLoop.onPropertyChanged(propVal); 585b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 586b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 58744303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 5885c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa disable(false); 5895c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa } 5905c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void persistBluetoothOnSetting(boolean bluetoothOn) { 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long origCallerIdentityToken = Binder.clearCallingIdentity(); 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON, 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bluetoothOn ? 1 : 0); 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(origCallerIdentityToken); 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ BondState getBondState() { 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** local cache of bonding state. 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* we keep our own state to track the intermediate state BONDING, which 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* bluez does not track. 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * All addreses must be passed in upper case. 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class BondState { 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final HashMap<String, Integer> mState = new HashMap<String, Integer>(); 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>(); 613c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 614c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private static final String AUTO_PAIRING_BLACKLIST = 615c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh "/etc/bluetooth/auto_pairing.conf"; 616c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private static final String DYNAMIC_AUTO_PAIRING_BLACKLIST = 617c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh "/data/misc/bluetooth/dynamic_auto_pairing.conf"; 618c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private ArrayList<String> mAutoPairingAddressBlacklist; 619c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private ArrayList<String> mAutoPairingExactNameBlacklist; 620c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private ArrayList<String> mAutoPairingPartialNameBlacklist; 621c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh // Addresses added to blacklist dynamically based on usage. 622c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private ArrayList<String> mAutoPairingDynamicAddressBlacklist; 623c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 624482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh 6252092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // If this is an outgoing connection, store the address. 6262092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // There can be only 1 pending outgoing connection at a time, 6272092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh private String mPendingOutgoingBonding; 6282092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 6292092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh private synchronized void setPendingOutgoingBonding(String address) { 6302092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mPendingOutgoingBonding = address; 6312092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 6322092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 6332092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh public synchronized String getPendingOutgoingBonding() { 6342092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh return mPendingOutgoingBonding; 6352092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 6362092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void loadBondState() { 638de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_TURNING_ON) { 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 641d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String []bonds = null; 642b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh String val = getPropertyInternal("Devices"); 643d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (val != null) { 644d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh bonds = val.split(","); 645d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bonds == null) { 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.clear(); 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log("found " + bonds.length + " bonded devices"); 651d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh for (String device : bonds) { 652d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mState.put(getAddressFromObjectPath(device).toUpperCase(), 653d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh BluetoothDevice.BOND_BONDED); 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setBondState(String address, int state) { 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setBondState(address, state, 0); 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** reason is ignored unless state == BOND_NOT_BONDED */ 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setBondState(String address, int state, int reason) { 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oldState = getBondState(address); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oldState == state) { 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6672092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 6682092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // Check if this was an pending outgoing bonding. 6692092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // If yes, reset the state. 6702092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (oldState == BluetoothDevice.BOND_BONDING) { 6712092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (address.equals(mPendingOutgoingBonding)) { 6722092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mPendingOutgoingBonding = null; 6732092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 6742092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 6752092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 6769b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state == BluetoothDevice.BOND_BONDED) { 6779b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh addProfileState(address); 6789b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } else if (state == BluetoothDevice.BOND_NONE) { 6799b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh removeProfileState(address); 6809b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 6819b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 682c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh // HID is handled by BluetoothService, other profiles 683c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh // will be handled by their respective services. 684c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh setInitialInputDevicePriority(mAdapter.getRemoteDevice(address), state); 685c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log(address + " bond state " + oldState + " -> " + state + " (" + 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reason + ")"); 688005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly Intent intent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED); 689005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 690005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, state); 691005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, oldState); 692005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (state == BluetoothDevice.BOND_NONE) { 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (reason <= 0) { 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "setBondState() called to unbond device, but reason code is " + 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "invalid. Overriding reason code with BOND_RESULT_REMOVED"); 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reason = BluetoothDevice.UNBOND_REASON_REMOVED; 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 698005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_REASON, reason); 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.remove(address); 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.put(address, state); 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isAutoPairingBlacklisted(String address) { 708c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingAddressBlacklist != null) { 709c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh for (String blacklistAddress : mAutoPairingAddressBlacklist) { 710c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (address.startsWith(blacklistAddress)) return true; 711c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 713482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh 714c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingDynamicAddressBlacklist != null) { 715c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh for (String blacklistAddress: mAutoPairingDynamicAddressBlacklist) { 716c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (address.equals(blacklistAddress)) return true; 717c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 718c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 719482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh String name = getRemoteName(address); 720482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh if (name != null) { 721c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingExactNameBlacklist != null) { 722c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh for (String blacklistName : mAutoPairingExactNameBlacklist) { 723c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (name.equals(blacklistName)) return true; 724c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 725738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh } 726738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh 727c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingPartialNameBlacklist != null) { 728c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh for (String blacklistName : mAutoPairingPartialNameBlacklist) { 729c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (name.startsWith(blacklistName)) return true; 730c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 731482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh } 732482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh } 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getBondState(String address) { 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer state = mState.get(address); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == null) { 739005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly return BluetoothDevice.BOND_NONE; 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return state.intValue(); 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 744e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh /*package*/ synchronized String[] listInState(int state) { 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<String> result = new ArrayList<String>(mState.size()); 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Map.Entry<String, Integer> e : mState.entrySet()) { 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (e.getValue().intValue() == state) { 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result.add(e.getKey()); 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result.toArray(new String[result.size()]); 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void addAutoPairingFailure(String address) { 755c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingDynamicAddressBlacklist == null) { 756c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingDynamicAddressBlacklist = new ArrayList<String>(); 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 758c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 759c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh updateAutoPairingData(address); 760c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingDynamicAddressBlacklist.add(address); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean isAutoPairingAttemptsInProgress(String address) { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getAttempt(address) != 0; 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void clearPinAttempts(String address) { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPinAttempt.remove(address); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean hasAutoPairingFailed(String address) { 772c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingDynamicAddressBlacklist == null) return false; 773c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 774c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh return mAutoPairingDynamicAddressBlacklist.contains(address); 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getAttempt(String address) { 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer attempt = mPinAttempt.get(address); 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (attempt == null) { 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return attempt.intValue(); 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void attempt(String address) { 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer attempt = mPinAttempt.get(address); 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newAttempt; 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (attempt == null) { 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newAttempt = 1; 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newAttempt = attempt.intValue() + 1; 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPinAttempt.put(address, new Integer(newAttempt)); 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 796c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private void copyAutoPairingData() { 797c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh File file = null; 798c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh FileInputStream in = null; 799c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh FileOutputStream out = null; 800c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 801c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh file = new File(DYNAMIC_AUTO_PAIRING_BLACKLIST); 802c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (file.exists()) return; 803c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 804c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh in = new FileInputStream(AUTO_PAIRING_BLACKLIST); 805c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh out= new FileOutputStream(DYNAMIC_AUTO_PAIRING_BLACKLIST); 806c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 807c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh byte[] buf = new byte[1024]; 808c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh int len; 809c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh while ((len = in.read(buf)) > 0) { 810c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh out.write(buf, 0, len); 811c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 812c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (FileNotFoundException e) { 813c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("FileNotFoundException: in copyAutoPairingData"); 814c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) { 815c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("IOException: in copyAutoPairingData"); 816c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } finally { 817c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 818c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (in != null) in.close(); 819c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (out != null) out.close(); 820c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) {} 821c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 822c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 823c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 824c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh public void readAutoPairingData() { 825c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingAddressBlacklist != null) return; 826c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh copyAutoPairingData(); 827c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh FileInputStream fstream = null; 828c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 829c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh fstream = new FileInputStream(DYNAMIC_AUTO_PAIRING_BLACKLIST); 830c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh DataInputStream in = new DataInputStream(fstream); 831c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh BufferedReader file = new BufferedReader(new InputStreamReader(in)); 832c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh String line; 833c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh while((line = file.readLine()) != null) { 834c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh line = line.trim(); 835c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (line.length() == 0 || line.startsWith("//")) continue; 836c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh String[] value = line.split("="); 837c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (value != null && value.length == 2) { 838c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh String[] val = value[1].split(","); 839c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (value[0].equalsIgnoreCase("AddressBlacklist")) { 840c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingAddressBlacklist = 841c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh new ArrayList<String>(Arrays.asList(val)); 842c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } else if (value[0].equalsIgnoreCase("ExactNameBlacklist")) { 843c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingExactNameBlacklist = 844c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh new ArrayList<String>(Arrays.asList(val)); 845c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } else if (value[0].equalsIgnoreCase("PartialNameBlacklist")) { 846c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingPartialNameBlacklist = 847c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh new ArrayList<String>(Arrays.asList(val)); 848c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } else if (value[0].equalsIgnoreCase("DynamicAddressBlacklist")) { 849c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh mAutoPairingDynamicAddressBlacklist = 850c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh new ArrayList<String>(Arrays.asList(val)); 851c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } else { 852c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh Log.e(TAG, "Error parsing Auto pairing blacklist file"); 853c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 854c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 855c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 856c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (FileNotFoundException e) { 857c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("FileNotFoundException: readAutoPairingData" + e.toString()); 858c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) { 859c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("IOException: readAutoPairingData" + e.toString()); 860c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } finally { 861c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (fstream != null) { 862c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 863c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh fstream.close(); 864c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) { 865c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh // Ignore 866c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 867c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 868c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 869c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 870c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh 871c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh // This function adds a bluetooth address to the auto pairing blacklis 872c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh // file. These addresses are added to DynamicAddressBlacklistSection 873c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh private void updateAutoPairingData(String address) { 874c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh BufferedWriter out = null; 875c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 876c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh out = new BufferedWriter(new FileWriter(DYNAMIC_AUTO_PAIRING_BLACKLIST, true)); 877c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh StringBuilder str = new StringBuilder(); 878c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (mAutoPairingDynamicAddressBlacklist.size() == 0) { 879c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh str.append("DynamicAddressBlacklist="); 880c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 881c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh str.append(address); 882c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh str.append(","); 883c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh out.write(str.toString()); 884c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (FileNotFoundException e) { 885c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("FileNotFoundException: updateAutoPairingData" + e.toString()); 886c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) { 887c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh log("IOException: updateAutoPairingData" + e.toString()); 888c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } finally { 889c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh if (out != null) { 890c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh try { 891c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh out.close(); 892c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } catch (IOException e) { 893c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh // Ignore 894c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 895c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 896c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 897c06fe59cb5a1bdd2a87d1aff3e35edf29a859979Jaikumar Ganesh } 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String toBondStateString(int bondState) { 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (bondState) { 902005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly case BluetoothDevice.BOND_NONE: 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "not bonded"; 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDING: 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonding"; 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDED: 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonded"; 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "??????"; 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9139519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh /*package*/ synchronized boolean isAdapterPropertiesEmpty() { 9149519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh return mAdapterProperties.isEmpty(); 9159519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh } 9169519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh 917d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/synchronized void getAllProperties() { 9188c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 920bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.clear(); 921d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 922d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String properties[] = (String [])getAdapterPropertiesNative(); 923d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The String Array consists of key-value pairs. 924d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (properties == null) { 925d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "*Error*: GetAdapterProperties returned NULL"); 926d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return; 927d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 928d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 9298bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int i = 0; i < properties.length; i++) { 9308bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh String name = properties[i]; 931efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh String newValue = null; 9328bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh int len; 9338bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (name == null) { 9348bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh Log.e(TAG, "Error:Adapter Property at index" + i + "is null"); 9358bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh continue; 9368bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 9377a9de8b425954e4039053038e4ec1762b866c83cDanica Chang if (name.equals("Devices") || name.equals("UUIDs")) { 938efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh StringBuilder str = new StringBuilder(); 9398bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh len = Integer.valueOf(properties[++i]); 9408bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int j = 0; j < len; j++) { 941efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(properties[++i]); 942efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(","); 943efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh } 944efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh if (len > 0) { 945efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh newValue = str.toString(); 9468bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 9478bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } else { 9488bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh newValue = properties[++i]; 9498bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 950bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.put(name, newValue); 951d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 952d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 953d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Add adapter object path property. 954d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String adapterPath = getAdapterPathNative(); 955d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (adapterPath != null) 956bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.put("ObjectPath", adapterPath + "/dev_"); 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 959d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ synchronized void setProperty(String name, String value) { 960bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.put(name, value); 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setName(String name) { 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == null) { 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 969d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyString("Name", name); 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 972d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh //TODO(): setPropertyString, setPropertyInteger, setPropertyBoolean 973d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Either have a single property function with Object as the parameter 974d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // or have a function for each property and then obfuscate in the JNI layer. 975d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The following looks dirty. 976d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyString(String key, String value) { 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 9788c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 979d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyStringNative(key, value); 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 982d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyInteger(String key, int value) { 983d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 9848c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 985d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyIntegerNative(key, value); 986d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 988d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyBoolean(String key, boolean value) { 989d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 9908c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 991d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyBooleanNative(key, value ? 1 : 0); 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 994d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /** 995d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Set the discoverability window for the device. A timeout of zero 996d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * makes the device permanently discoverable (if the device is 997d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * discoverable). Setting the timeout to a nonzero value does not make 998d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * a device discoverable; you need to call setMode() to make the device 999d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * explicitly discoverable. 1000d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 1001d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param timeout_s The discoverable timeout in seconds. 1002d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh */ 1003d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean setDiscoverableTimeout(int timeout) { 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 1006d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyInteger("DiscoverableTimeout", timeout); 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 100912835478ee687a493d1b5882e67b6725bd539c26Nick Pelly public synchronized boolean setScanMode(int mode, int duration) { 101018b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, 101118b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly "Need WRITE_SECURE_SETTINGS permission"); 1012de893f550301a60274e87aa8168225e7a7a42184Nick Pelly boolean pairable = false; 1013de893f550301a60274e87aa8168225e7a7a42184Nick Pelly boolean discoverable = false; 101412835478ee687a493d1b5882e67b6725bd539c26Nick Pelly 1015de893f550301a60274e87aa8168225e7a7a42184Nick Pelly switch (mode) { 1016de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 101712835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT); 1018d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = false; 1019d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 1020de893f550301a60274e87aa8168225e7a7a42184Nick Pelly break; 1021de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 102212835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT); 1023d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 1024d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 1025005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 1026de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 102712835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT); 1028d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 1029d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = true; 103012835478ee687a493d1b5882e67b6725bd539c26Nick Pelly Message msg = mHandler.obtainMessage(MESSAGE_DISCOVERABLE_TIMEOUT); 103112835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.sendMessageDelayed(msg, duration * 1000); 103212835478ee687a493d1b5882e67b6725bd539c26Nick Pelly if (DBG) Log.d(TAG, "BT Discoverable for " + duration + " seconds"); 1033005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 1034de893f550301a60274e87aa8168225e7a7a42184Nick Pelly default: 1035de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Log.w(TAG, "Requested invalid scan mode " + mode); 1036de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return false; 1037d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1038d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh setPropertyBoolean("Pairable", pairable); 1039d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh setPropertyBoolean("Discoverable", discoverable); 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1041d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return true; 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1044b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh /*package*/ synchronized String getProperty(String name) { 1045b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh if (!isEnabledInternal()) return null; 1046b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh return getPropertyInternal(name); 1047b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh } 1048b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh 1049b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh /*package*/ synchronized String getPropertyInternal(String name) { 1050bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly if (!mAdapterProperties.isEmpty()) 1051bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return mAdapterProperties.get(name); 1052d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh getAllProperties(); 1053bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return mAdapterProperties.get(name); 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1056d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getAddress() { 1057d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1058d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Address"); 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1061d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getName() { 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1063d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Name"); 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1067d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Returns the user-friendly name of a remote device. This value is 1068d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * returned from our local cache, which is updated when onPropertyChange 1069d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * event is received. 1070d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Do not expect to retrieve the updated remote name immediately after 1071d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * changing the name on the remote device. 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1073d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Bluetooth address of remote device. 1074d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 1075d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return The user-friendly name of the specified remote device. 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1077d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getRemoteName(String address) { 1078d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1079005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1080d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1081d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 108255929a958bf0e482c8e4d7df3dd75957f1e9d871Jaikumar Ganesh return getRemoteDeviceProperty(address, "Name"); 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the discoverability window for the device. A timeout of zero 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * means that the device is permanently discoverable (if the device is 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the discoverable mode). 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The discoverability window of the device, in seconds. A negative 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value indicates an error. 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getDiscoverableTimeout() { 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1095d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String timeout = getProperty("DiscoverableTimeout"); 1096d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (timeout != null) 1097d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(timeout); 1098d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 1099d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return -1; 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getScanMode() { 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 11048c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) 1105de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 1106d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1107d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean pairable = getProperty("Pairable").equals("true"); 1108d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean discoverable = getProperty("Discoverable").equals("true"); 1109d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return bluezStringToScanMode (pairable, discoverable); 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1112d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean startDiscovery() { 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 11158c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11168c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1117d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return startDiscoveryNative(); 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1120d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean cancelDiscovery() { 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 11238c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11248c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1125d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return stopDiscoveryNative(); 1126d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1127d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1128d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean isDiscovering() { 1129d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1130d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return mIsDiscovering; 1131d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1132d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1133d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ void setIsDiscovering(boolean isDiscovering) { 1134d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mIsDiscovering = isDiscovering; 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean createBond(String address) { 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 11408c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11418c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1142005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11472092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (mBondState.getPendingOutgoingBonding() != null) { 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project log("Ignoring createBond(): another device is bonding"); 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a different device is currently bonding, fail 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check for bond state only if we are not performing auto 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pairing exponential back-off attempts. 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mBondState.isAutoPairingAttemptsInProgress(address) && 1156005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.getBondState(address) != BluetoothDevice.BOND_NONE) { 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project log("Ignoring createBond(): this device is already bonding or bonded"); 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11613fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (address.equals(mDockAddress)) { 11623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (!writeDockPin()) { 11633fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh log("Error while writing Pin for the dock"); 11643fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 11653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 11663fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 11673fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1168d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!createPairedDeviceNative(address, 60000 /* 1 minute */)) { 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11722092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mBondState.setPendingOutgoingBonding(address); 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); 11742092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean cancelBondProcess(String address) { 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 11818c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11828c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1183005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) { 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1191005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 1193d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh cancelDeviceCreationNative(address); 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean removeBond(String address) { 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 12008c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 12018c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1202005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1205f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 12069b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 1207f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh state.sendMessage(BluetoothDeviceProfileState.UNPAIR); 12089b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 12099b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } else { 12109b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 12119b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 12129b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 12139b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 12149b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public synchronized boolean removeBondInternal(String address) { 1215d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return removeDeviceNative(getObjectPathFromAddress(address)); 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized String[] listBonds() { 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.listInState(BluetoothDevice.BOND_BONDED); 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getBondState(String address) { 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1225005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1226b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.getBondState(address.toUpperCase()); 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12313fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh public synchronized boolean isBluetoothDock(String address) { 12326e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 12336e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.MODE_PRIVATE); 12346e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 12356e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh return sp.contains(SHARED_PREFERENCE_DOCK_ADDRESS + address); 12363fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 12373fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1238545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh public synchronized boolean connectInputDevice(BluetoothDevice device) { 1239545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1240545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 1241545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1242545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh String objectPath = getObjectPathFromAddress(device.getAddress()); 124305a1863cebcc8e318283f3f4a49ba69d83b62866Jaikumar Ganesh if (objectPath == null || 124405a1863cebcc8e318283f3f4a49ba69d83b62866Jaikumar Ganesh getInputDeviceState(device) != BluetoothInputDevice.STATE_DISCONNECTED || 1245545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_OFF) { 1246545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return false; 1247545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1248de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress()); 1249de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh if (state != null) { 1250de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh Message msg = new Message(); 1251de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.CONNECT_HID_OUTGOING; 1252de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh msg.obj = state; 1253de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh mHidProfileState.sendMessage(msg); 1254545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return true; 1255545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1256545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return false; 1257545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1258545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1259de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh public synchronized boolean connectInputDeviceInternal(BluetoothDevice device) { 1260de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh String objectPath = getObjectPathFromAddress(device.getAddress()); 1261de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTING); 1262de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh if (!connectInputDeviceNative(objectPath)) { 1263de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTED); 1264de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh return false; 1265de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh } 1266de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh return true; 1267de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh } 1268de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh 1269545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh public synchronized boolean disconnectInputDevice(BluetoothDevice device) { 1270545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1271545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 1272545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1273545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh String objectPath = getObjectPathFromAddress(device.getAddress()); 1274545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh if (objectPath == null || getConnectedInputDevices().length == 0) { 1275545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return false; 1276545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1277de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress()); 1278de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh if (state != null) { 1279de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh Message msg = new Message(); 1280de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HID_OUTGOING; 1281de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh msg.obj = state; 1282de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh mHidProfileState.sendMessage(msg); 1283545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return true; 1284545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1285545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return false; 1286545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1287545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1288de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh public synchronized boolean disconnectInputDeviceInternal(BluetoothDevice device) { 1289de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh String objectPath = getObjectPathFromAddress(device.getAddress()); 1290de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTING); 1291de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh if (!disconnectInputDeviceNative(objectPath)) { 1292de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTED); 1293de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh return false; 1294de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh } 1295de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh return true; 1296de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh } 1297de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh 1298545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh public synchronized int getInputDeviceState(BluetoothDevice device) { 1299545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1300545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1301545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh if (mInputDevices.get(device) == null) { 1302545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return BluetoothInputDevice.STATE_DISCONNECTED; 1303545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1304df7627db715a7a2e7f646f02a07caf2347bb90b8Adam Powell return mInputDevices.get(device); 1305545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1306545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1307545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh public synchronized BluetoothDevice[] getConnectedInputDevices() { 1308545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1309545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh Set<BluetoothDevice> devices = lookupInputDevicesMatchingStates( 1310545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh new int[] {BluetoothInputDevice.STATE_CONNECTED}); 1311545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return devices.toArray(new BluetoothDevice[devices.size()]); 1312545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1313545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1314545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh public synchronized int getInputDevicePriority(BluetoothDevice device) { 1315545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1316545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return Settings.Secure.getInt(mContext.getContentResolver(), 1317545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()), 1318545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh BluetoothInputDevice.PRIORITY_UNDEFINED); 1319545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1320545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1321545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh public synchronized boolean setInputDevicePriority(BluetoothDevice device, int priority) { 1322545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1323545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 1324545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { 1325545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return false; 1326545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1327545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return Settings.Secure.putInt(mContext.getContentResolver(), 1328545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()), 1329545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh priority); 1330545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1331545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1332545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh /*package*/synchronized Set<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) { 1333545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh Set<BluetoothDevice> inputDevices = new HashSet<BluetoothDevice>(); 1334545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh if (mInputDevices.isEmpty()) { 1335545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return inputDevices; 1336545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1337545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh for (BluetoothDevice device: mInputDevices.keySet()) { 1338545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh int inputDeviceState = getInputDeviceState(device); 1339545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh for (int state : states) { 1340545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh if (state == inputDeviceState) { 1341545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh inputDevices.add(device); 1342545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh break; 1343545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1344545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1345545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1346545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return inputDevices; 1347545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1348545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1349545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh private synchronized void handleInputDeviceStateChange(BluetoothDevice device, int state) { 1350545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh int prevState; 1351545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh if (mInputDevices.get(device) == null) { 1352545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh prevState = BluetoothInputDevice.STATE_DISCONNECTED; 1353545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } else { 1354545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh prevState = mInputDevices.get(device); 1355545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1356545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh if (prevState == state) return; 1357545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1358545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh mInputDevices.put(device, state); 1359545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1360545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh if (getInputDevicePriority(device) > 1361545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh BluetoothInputDevice.PRIORITY_OFF && 1362545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh state == BluetoothInputDevice.STATE_CONNECTING || 1363545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh state == BluetoothInputDevice.STATE_CONNECTED) { 1364545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh // We have connected or attempting to connect. 1365545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh // Bump priority 1366545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_AUTO_CONNECT); 1367545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1368545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1369545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh Intent intent = new Intent(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED); 1370545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 1371545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, prevState); 1372545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh intent.putExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, state); 1373545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 1374545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1375545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh if (DBG) log("InputDevice state : device: " + device + " State:" + prevState + "->" + state); 1376545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1377545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1378545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 137956d26139659c2414d289194c63860ff27ab80da0Jaikumar Ganesh /*package*/ void handleInputDevicePropertyChange(String address, boolean connected) { 1380545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh int state = connected ? BluetoothInputDevice.STATE_CONNECTED : 1381545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh BluetoothInputDevice.STATE_DISCONNECTED; 1382545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh BluetoothDevice device = mAdapter.getRemoteDevice(address); 1383545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh handleInputDeviceStateChange(device, state); 1384545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 1385545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 1386c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh private void setInitialInputDevicePriority(BluetoothDevice device, int state) { 1387c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh switch (state) { 1388c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh case BluetoothDevice.BOND_BONDED: 1389c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh if (getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_UNDEFINED) { 1390c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_ON); 1391c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh } 1392c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh break; 1393c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh case BluetoothDevice.BOND_NONE: 1394c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_UNDEFINED); 1395c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh break; 1396c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh } 1397c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh } 1398c3ee99d9eb7e8b4b20c2b8f1c548373e1017e0d3Jaikumar Ganesh 13999488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh /*package*/ boolean isRemoteDeviceInCache(String address) { 1400bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return (mDeviceProperties.get(address) != null); 14019488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 14029488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh 14039488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh /*package*/ String[] getRemoteDeviceProperties(String address) { 14048c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return null; 14058c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 14069488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh String objectPath = getObjectPathFromAddress(address); 14079488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh return (String [])getDevicePropertiesNative(objectPath); 14089488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 14099488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh 1410d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ synchronized String getRemoteDeviceProperty(String address, String property) { 1411bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly Map<String, String> properties = mDeviceProperties.get(address); 1412d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (properties != null) { 1413d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return properties.get(property); 1414d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 1415d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Query for remote device properties, again. 1416d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // We will need to reload the cache when we switch Bluetooth on / off 1417d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // or if we crash. 141810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (updateRemoteDevicePropertiesCache(address)) 1419d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getRemoteDeviceProperty(address, property); 14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1421d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getRemoteDeviceProperty: " + property + "not present:" + address); 1422d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 142510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh /* package */ synchronized boolean updateRemoteDevicePropertiesCache(String address) { 142610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh String[] propValues = getRemoteDeviceProperties(address); 142710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (propValues != null) { 142810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh addRemoteDeviceProperties(address, propValues); 142910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return true; 143010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 143110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return false; 143210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 143310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 1434d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ synchronized void addRemoteDeviceProperties(String address, String[] properties) { 1435395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh /* 1436395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh * We get a DeviceFound signal every time RSSI changes or name changes. 1437395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh * Don't create a new Map object every time */ 1438bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly Map<String, String> propertyValues = mDeviceProperties.get(address); 1439efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh if (propertyValues == null) { 1440395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh propertyValues = new HashMap<String, String>(); 1441395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh } 1442395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh 14438bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int i = 0; i < properties.length; i++) { 14448bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh String name = properties[i]; 1445efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh String newValue = null; 14468bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh int len; 14478bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (name == null) { 14488bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh Log.e(TAG, "Error: Remote Device Property at index" + i + "is null"); 14498bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh continue; 14508bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 14518bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (name.equals("UUIDs") || name.equals("Nodes")) { 1452efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh StringBuilder str = new StringBuilder(); 14538bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh len = Integer.valueOf(properties[++i]); 14548bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int j = 0; j < len; j++) { 1455efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(properties[++i]); 1456efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(","); 1457efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh } 1458efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh if (len > 0) { 1459efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh newValue = str.toString(); 14608bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 1461d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 14628bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh newValue = properties[++i]; 1463d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1464efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh 14658bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh propertyValues.put(name, newValue); 14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1467bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties.put(address, propertyValues); 146810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 146910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // We have added a new remote device or updated its properties. 147010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // Also update the serviceChannel cache. 147110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh updateDeviceServiceChannelCache(address); 14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1474d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ void removeRemoteDeviceProperties(String address) { 1475bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties.remove(address); 14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1478d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ synchronized void setRemoteDeviceProperty(String address, String name, 1479d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String value) { 1480bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly Map <String, String> propVal = mDeviceProperties.get(address); 1481d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (propVal != null) { 1482d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh propVal.put(name, value); 1483bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties.put(address, propVal); 1484d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 1485d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "setRemoteDeviceProperty for a device not in cache:" + address); 14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1490efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Sets the remote device trust state. 1491efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 1492efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * @return boolean to indicate operation success or fail 1493efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1494efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean setTrust(String address, boolean value) { 1495005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1496e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1497e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly "Need BLUETOOTH_ADMIN permission"); 1498efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1499efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1500efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 15018c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 15028c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1503efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return setDevicePropertyBooleanNative(getObjectPathFromAddress(address), "Trusted", 1504efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue value ? 1 : 0); 1505efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1506efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1507efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1508efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Gets the remote device trust state as boolean. 1509efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Note: this value may be 1510efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * retrieved from cache if we retrieved the data before * 1511efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 1512efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * @return boolean to indicate trust or untrust state 1513efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1514efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean getTrustState(String address) { 1515005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1516efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1517efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1518efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1519efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1520efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue String val = getRemoteDeviceProperty(address, "Trusted"); 1521efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue if (val == null) { 1522efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1523efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } else { 1524efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return val.equals("true") ? true : false; 1525efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1526efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1527efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1528efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1529d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the remote major, minor classes encoded as a 32-bit 15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * integer. 15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: this value is retrieved from cache, because we get it during 15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * remote-device discovery. 15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return 32-bit integer encoding the remote major, minor, and service 15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * classes. 15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getRemoteClass(String address) { 1539005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1540ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1541ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly return BluetoothClass.ERROR; 15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1543d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String val = getRemoteDeviceProperty(address, "Class"); 1544d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (val == null) 1545d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return BluetoothClass.ERROR; 1546d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else { 1547d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(val); 1548d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1550d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1553dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * Gets the UUIDs supported by the remote device 15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1555dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @return array of 128bit ParcelUuids 15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1557dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public synchronized ParcelUuid[] getRemoteUuids(String address) { 15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1559005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15621caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return getUuidFromCache(address); 15631caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 15641caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 15651caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private ParcelUuid[] getUuidFromCache(String address) { 1566d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String value = getRemoteDeviceProperty(address, "UUIDs"); 1567dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh if (value == null) return null; 1568dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1569dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh String[] uuidStrings = null; 1570d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The UUIDs are stored as a "," separated string. 1571dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuidStrings = value.split(","); 1572dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; 1573dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1574dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh for (int i = 0; i < uuidStrings.length; i++) { 1575dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuids[i] = ParcelUuid.fromString(uuidStrings[i]); 1576dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh } 1577d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return uuids; 15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 158016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** 158116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Connect and fetch new UUID's using SDP. 158216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * The UUID's found are broadcast as intents. 158316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Optionally takes a uuid and callback to fetch the RFCOMM channel for the 158416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * a given uuid. 158516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to broadcast UUID intents on success 158616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to handle the failure case for 158716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * callback and broadcast intents. 158816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly */ 158916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public synchronized boolean fetchRemoteUuids(String address, ParcelUuid uuid, 159016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback) { 15911caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 15928c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 15938c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 15941caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (!BluetoothAdapter.checkBluetoothAddress(address)) { 15951caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return false; 15961caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 15971caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 159816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = new RemoteService(address, uuid); 159916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null && mUuidCallbackTracker.get(service) != null) { 160016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // An SDP query for this address & uuid is already in progress 160116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Do not add this callback for the uuid 160216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 160316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 160416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 16051caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (mUuidIntentTracker.contains(address)) { 16061caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // An SDP query for this address is already in progress 160716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Add this uuid onto the in-progress SDP query 160816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 160916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 161016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 16111caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return true; 16121caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 16131caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 16141caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh boolean ret; 16150e09030977aea8b40fd177139528d4b5637c9771Jaikumar Ganesh // Just do the SDP if the device is already created and UUIDs are not 16160e09030977aea8b40fd177139528d4b5637c9771Jaikumar Ganesh // NULL, else create the device and then do SDP. 16170e09030977aea8b40fd177139528d4b5637c9771Jaikumar Ganesh if (isRemoteDeviceInCache(address) && getRemoteUuids(address) != null) { 16181caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String path = getObjectPathFromAddress(address); 16191caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (path == null) return false; 16201caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 16211caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // Use an empty string for the UUID pattern 16221caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh ret = discoverServicesNative(path, ""); 16231caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } else { 16241caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh ret = createDeviceNative(address); 16251caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 16261caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 16271caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker.add(address); 162816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 162916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 163016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 16311caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 16321caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT); 16331caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh message.obj = address; 16341caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY); 16351caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return ret; 16361caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 16371caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1639d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the rfcomm channel associated with the UUID. 164016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Pulls records from the cache only. 16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1642d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Address of the remote device 1643dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @param uuid ParcelUuid of the service attribute 16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1645d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return rfcomm channel associated with the service attribute 164610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh * -1 on error 16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1648dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public int getRemoteServiceChannel(String address, ParcelUuid uuid) { 16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 16508c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 16518c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1652005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1653b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 165510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // Check if we are recovering from a crash. 165610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (mDeviceProperties.isEmpty()) { 165710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (!updateRemoteDevicePropertiesCache(address)) 165810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 165910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 166010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 166110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address); 166210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (value != null && value.containsKey(uuid)) 166310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return value.get(uuid); 166410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setPin(String address, byte[] pin) { 16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 16708c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 16718c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pin == null || pin.length <= 0 || pin.length > 16 || 1673005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly !BluetoothAdapter.checkBluetoothAddress(address)) { 16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "setPin(" + address + ") called but no native data available, " + 16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " or by bluez.\n"); 16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bluez API wants pin as a string 16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pinString; 16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pinString = new String(pin, "UTF8"); 16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (UnsupportedEncodingException uee) { 16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "UTF8 not supported?!?"); 16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return setPinNative(address, pinString, data.intValue()); 16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1695b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPasskey(String address, int passkey) { 1696b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1697b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 16988c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 16998c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1700005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (passkey < 0 || passkey > 999999 || !BluetoothAdapter.checkBluetoothAddress(address)) { 1701b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1702b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1703b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1704b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1705b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1706b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1707b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1708b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1709b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1710b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1711b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPasskeyNative(address, passkey, data.intValue()); 1712b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1713b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1714b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPairingConfirmation(String address, boolean confirm) { 1715b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1716b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 17178c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 17188c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1719b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1720b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1721b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1722b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1723b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1724b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1725b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1726b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1727b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPairingConfirmationNative(address, confirm, data.intValue()); 1728b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1729b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1730b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean cancelPairingUserInput(String address) { 17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 17338c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 17348c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1735005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1738005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 1739397d8f4f4829a45f4fe7a672cc395466bbc0f442Jaikumar Ganesh BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 1743b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "cancelUserInputNative(" + address + ") called but no native data " + 1744b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "available, ignoring. Maybe the PasskeyAgent Request was already cancelled " + 1745b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "by the remote or by bluez.\n"); 17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1748b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return cancelPairingUserInputNative(address, data.intValue()); 17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17518c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh /*package*/ void updateDeviceServiceChannelCache(String address) { 175210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh ParcelUuid[] deviceUuids = getRemoteUuids(address); 175310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // We are storing the rfcomm channel numbers only for the uuids 175410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // we are interested in. 175510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh int channel; 175616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("updateDeviceServiceChannelCache(" + address + ")"); 175716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 175816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly ArrayList<ParcelUuid> applicationUuids = new ArrayList(); 175916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 176016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 176116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (RemoteService service : mUuidCallbackTracker.keySet()) { 176216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 176316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly applicationUuids.add(service.uuid); 176416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 176516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 176616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 176710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 176810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh Map <ParcelUuid, Integer> value = new HashMap<ParcelUuid, Integer>(); 176916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 177016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for default uuids 177116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : RFCOMM_UUIDS) { 177210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 177316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = getDeviceServiceChannelNative(getObjectPathFromAddress(address), 177416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly uuid.toString(), 0x0004); 177516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("\tuuid(system): " + uuid + " " + channel); 177610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh value.put(uuid, channel); 177710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 177810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 177916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for application requested uuids 178016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : applicationUuids) { 178116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 178216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = getDeviceServiceChannelNative(getObjectPathFromAddress(address), 178316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly uuid.toString(), 0x0004); 178416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("\tuuid(application): " + uuid + " " + channel); 178516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly value.put(uuid, channel); 178616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 178716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 178816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 178916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 179016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Make application callbacks 179116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 179216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 179316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 179416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 179516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = -1; 179616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (value.get(service.uuid) != null) { 179716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = value.get(service.uuid); 179816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 179916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (channel != -1) { 180016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("Making callback for " + service.uuid + " with result " + 180116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel); 180216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 180316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 180416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 180516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(channel); 180616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 180716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 180816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 180916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 181016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 181116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 181216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 181316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 181416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Update cache 181516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mDeviceServiceChannelCache.put(address, value); 181616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 181710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 181810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 181924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly /** 182024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * b is a handle to a Binder instance, so that this service can be notified 182124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * for Applications that terminate unexpectedly, to clean there service 182224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * records 182324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly */ 182424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid, 182524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int channel, IBinder b) { 18268c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 18278c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 18288c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 182924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (serviceName == null || uuid == null || channel < 1 || 183024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) { 183124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 183224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 183324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) { 183424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Log.w(TAG, "Attempted to register a reserved UUID: " + uuid); 183524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 183624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 183724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle = addRfcommServiceRecordNative(serviceName, 183824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(), 183924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly (short)channel); 184024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (DBG) log("new handle " + Integer.toHexString(handle)); 184124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (handle == -1) { 184224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 184324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 184424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 184524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int pid = Binder.getCallingPid(); 184624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.put(new Integer(handle), new Integer(pid)); 184724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly try { 184824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly b.linkToDeath(new Reaper(handle, pid), 0); 184924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } catch (RemoteException e) {} 185024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return handle; 185124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 185224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 185324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void removeServiceRecord(int handle) { 185424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 185524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly "Need BLUETOOTH permission"); 185624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly checkAndRemoveRecord(handle, Binder.getCallingPid()); 185724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 185824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 185924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private synchronized void checkAndRemoveRecord(int handle, int pid) { 186024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer handleInt = new Integer(handle); 186124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer owner = mServiceRecordToPid.get(handleInt); 186224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (owner != null && pid == owner.intValue()) { 186324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (DBG) log("Removing service record " + Integer.toHexString(handle) + " for pid " + 186424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pid); 186524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.remove(handleInt); 186624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly removeServiceRecordNative(handle); 186724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 186824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 186924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 187024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private class Reaper implements IBinder.DeathRecipient { 187124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int pid; 187224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle; 187324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Reaper(int handle, int pid) { 187424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly this.pid = pid; 187524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly this.handle = handle; 187624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 187724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void binderDied() { 187824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly synchronized (BluetoothService.this) { 187924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (DBG) log("Tracked app " + pid + " died"); 188024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly checkAndRemoveRecord(handle, pid); 188124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 188224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 188324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 188424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 18886e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (intent == null) return; 18896e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String action = intent.getAction(); 18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver resolver = context.getContentResolver(); 18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Query the airplane mode from Settings.System just to make sure that 18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // some random app is not sending this intent and disabling bluetooth 18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean enabled = !isAirplaneModeOn(); 18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If bluetooth is currently expected to be on, then enable or disable bluetooth 18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) { 18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (enabled) { 1899105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project enable(false); 19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project disable(false); 19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19046e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else if (Intent.ACTION_DOCK_EVENT.equals(action)) { 19056e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 19066e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh Intent.EXTRA_DOCK_STATE_UNDOCKED); 19076e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (DBG) Log.v(TAG, "Received ACTION_DOCK_EVENT with State:" + state); 19086e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) { 19096e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockAddress = null; 19106e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockPin = null; 19116e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else { 19126e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences.Editor editor = 19136e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 19146e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.MODE_PRIVATE).edit(); 19156e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh editor.putBoolean(SHARED_PREFERENCE_DOCK_ADDRESS + mDockAddress, true); 19166e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh editor.commit(); 19176e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } 19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19226e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private void registerForAirplaneMode(IntentFilter filter) { 192344303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final ContentResolver resolver = mContext.getContentResolver(); 192444303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String airplaneModeRadios = Settings.System.getString(resolver, 19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_RADIOS); 192644303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String toggleableRadios = Settings.System.getString(resolver, 192744303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 192844303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 192944303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneSensitive = airplaneModeRadios == null ? true : 193044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH); 193144303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneToggleable = toggleableRadios == null ? false : 193244303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH); 193344303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsAirplaneSensitive) { 19356e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Returns true if airplane mode is currently on */ 19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean isAirplaneModeOn() { 19419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Settings.System.getInt(mContext.getContentResolver(), 19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_ON, 0) == 1; 19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19451caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /* Broadcast the Uuid intent */ 19461caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /*package*/ synchronized void sendUuidIntent(String address) { 19476179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh ParcelUuid[] uuid = getUuidFromCache(address); 19486179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_UUID); 19492d3b98d868cda30535505b2a2fba47aa1c9c052bJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 19506179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid); 19516179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 19521caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 19536179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh if (mUuidIntentTracker.contains(address)) 19541caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker.remove(address); 195516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 195616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 195716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 195816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ synchronized void makeServiceChannelCallbacks(String address) { 195916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 196016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 196116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 196216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 196316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("Cleaning up failed UUID channel lookup: " + service.address + 196416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly " " + service.uuid); 196516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 196616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 196716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 196816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(-1); 196916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 197016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 197116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 197216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 197316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 197416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 19751caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 19761caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1979105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project switch(mBluetoothState) { 1980de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_OFF: 198124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth OFF\n"); 1982105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1983de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_TURNING_ON: 198424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth TURNING ON\n"); 1985105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1986de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_TURNING_OFF: 198724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth TURNING OFF\n"); 1988105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1989de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_ON: 199024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth ON\n"); 1991105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1992105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 199324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive); 199444303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey pw.println("mIsAirplaneToggleable = " + mIsAirplaneToggleable); 199524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 199624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local address = " + getAddress()); 199724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local name = " + getName()); 199824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("isDiscovering() = " + isDiscovering()); 1999105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 2000105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BluetoothHeadset headset = new BluetoothHeadset(mContext, null); 2001105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 2002105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--Known devices--"); 2003bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly for (String address : mDeviceProperties.keySet()) { 20041eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly int bondState = mBondState.getBondState(address); 2005105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.printf("%s %10s (%d) %s\n", address, 20061eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly toBondStateString(bondState), 2007105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBondState.getAttempt(address), 2008105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project getRemoteName(address)); 200924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 201024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Map<ParcelUuid, Integer> uuidChannels = mDeviceServiceChannelCache.get(address); 201124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (uuidChannels == null) { 201224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\tuuids = null"); 201324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } else { 201424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly for (ParcelUuid uuid : uuidChannels.keySet()) { 201524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer channel = uuidChannels.get(uuid); 201624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (channel == null) { 201724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\t" + uuid); 201824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } else { 201924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\t" + uuid + " RFCOMM channel = " + channel); 20201eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly } 20211eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly } 20221eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly } 202316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (RemoteService service : mUuidCallbackTracker.keySet()) { 202416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 202516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly pw.println("\tPENDING CALLBACK: " + service.uuid); 202616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 202716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 2028105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 2029105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 2030d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String value = getProperty("Devices"); 20311eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly String[] devicesObjectPath = null; 2032d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (value != null) { 2033d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh devicesObjectPath = value.split(","); 2034d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 2035105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--ACL connected devices--"); 203624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (devicesObjectPath != null) { 203724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly for (String device : devicesObjectPath) { 203824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println(getAddressFromObjectPath(device)); 203924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 2040105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 2041105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 2042105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Rather not do this from here, but no-where else and I need this 2043105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // dump 2044105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--Headset Service--"); 2045740e39be6af3e366a4b82c030b5ea67ab144b42aJaikumar Ganesh switch (headset.getState(headset.getCurrentHeadset())) { 2046105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_DISCONNECTED: 2047105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_DISCONNECTED"); 2048105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 2049105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_CONNECTING: 2050105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_CONNECTING"); 2051105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 2052105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_CONNECTED: 2053105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_CONNECTED"); 2054105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 2055105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_ERROR: 2056105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_ERROR"); 2057105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 2058105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 20596c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly 206024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\ngetCurrentHeadset() = " + headset.getCurrentHeadset()); 206124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("getBatteryUsageHint() = " + headset.getBatteryUsageHint()); 2062105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project headset.close(); 206324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\n--Application Service Records--"); 206424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly for (Integer handle : mServiceRecordToPid.keySet()) { 206524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer pid = mServiceRecordToPid.get(handle); 206624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle)); 206724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 20689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2070d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) { 2071d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (pairable && discoverable) 2072bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 2073d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else if (pairable && !discoverable) 2074bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 2075d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 2076bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 20779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static String scanModeToBluezString(int mode) { 20809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mode) { 2081bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 20829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "off"; 2083bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 20849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "connectable"; 2085bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 20869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "discoverable"; 20879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 20899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2091d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getAddressFromObjectPath(String objectPath) { 2092b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh String adapterObjectPath = getPropertyInternal("ObjectPath"); 2093d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (adapterObjectPath == null || objectPath == null) { 2094d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: AdpaterObjectPath:" + adapterObjectPath + 2095d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " or deviceObjectPath:" + objectPath + " is null"); 2096d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 2097d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 2098d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!objectPath.startsWith(adapterObjectPath)) { 2099d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: AdpaterObjectPath:" + adapterObjectPath + 2100d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " is not a prefix of deviceObjectPath:" + objectPath + 2101d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh "bluetoothd crashed ?"); 2102d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 2103d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 2104d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String address = objectPath.substring(adapterObjectPath.length()); 2105d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (address != null) return address.replace('_', ':'); 2106d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2107d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: Address being returned is null"); 2108d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 2109d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 2110d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2111d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getObjectPathFromAddress(String address) { 2112b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh String path = getPropertyInternal("ObjectPath"); 2113d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (path == null) { 2114d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "Error: Object Path is null"); 2115d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 2116d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 2117d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh path = path + address.replace(":", "_"); 2118d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return path; 2119d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 2120d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2121b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh /*package */ void setLinkTimeout(String address, int num_slots) { 2122b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh String path = getObjectPathFromAddress(address); 2123b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh boolean result = setLinkTimeoutNative(path, num_slots); 2124b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 2125b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh if (!result) log("Set Link Timeout to:" + num_slots + " slots failed"); 2126b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh } 2127b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 21289b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectHeadset(String address) { 2129f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 21309b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2131f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2132f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING; 2133f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2134f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.sendMessage(msg); 2135f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh return true; 21369b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21379b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 21389b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21399b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21409b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectHeadset(String address) { 2141f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 21429b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2143f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2144f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HFP_OUTGOING; 2145f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2146f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.sendMessage(msg); 21479b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 21489b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21499b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 21509b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21519b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21529b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectSink(String address) { 2153f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 21549b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2155f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2156f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING; 2157f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2158f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.sendMessage(msg); 2159f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh return true; 21609b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21619b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 21629b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21639b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21649b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectSink(String address) { 2165f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 21669b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2167f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2168f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_A2DP_OUTGOING; 2169f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2170f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.sendMessage(msg); 21719b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 21729b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21739b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 21749b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21759b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 2176f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private BluetoothDeviceProfileState addProfileState(String address) { 2177f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 21789b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) return state; 21799b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 2180f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh state = new BluetoothDeviceProfileState(mContext, address, this, mA2dpService); 2181f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.put(address, state); 21829b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.start(); 21839b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return state; 21849b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21859b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21869b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private void removeProfileState(String address) { 2187f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.remove(address); 21889b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21899b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21909b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private void initProfileState() { 21919b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh String []bonds = null; 21929b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh String val = getPropertyInternal("Devices"); 21939b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (val != null) { 21949b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh bonds = val.split(","); 21959b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21969b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (bonds == null) { 21979b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return; 21989b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21999b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22009b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh for (String path : bonds) { 22019b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh String address = getAddressFromObjectPath(path); 2202f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = addProfileState(address); 22039b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh // Allow 8 secs for SDP records to get registered. 22049b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 2205f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.what = BluetoothDeviceProfileState.AUTO_CONNECT_PROFILES; 22069b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessageDelayed(msg, 8000); 22079b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22089b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22099b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22109b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean notifyIncomingConnection(String address) { 2211f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = 2212f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.get(address); 22139b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 22149b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 2215f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.what = BluetoothDeviceProfileState.CONNECT_HFP_INCOMING; 22169b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(msg); 22179b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 22189b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22199b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 22209b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22219b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22229b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /*package*/ boolean notifyIncomingA2dpConnection(String address) { 2223f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = 2224f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.get(address); 22259b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 22269b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 2227f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.what = BluetoothDeviceProfileState.CONNECT_A2DP_INCOMING; 22289b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(msg); 22299b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 22309b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22319b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 22329b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22339b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22349b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /*package*/ void setA2dpService(BluetoothA2dpService a2dpService) { 22359b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh mA2dpService = a2dpService; 22369b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22379b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void log(String msg) { 22399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, msg); 22409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2241d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2242d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native static void classInitNative(); 2243d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void initializeNativeDataNative(); 2244d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setupNativeDataNative(); 2245d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean tearDownNativeDataNative(); 2246d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void cleanupNativeDataNative(); 2247d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native String getAdapterPathNative(); 2248d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2249d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int isEnabledNative(); 2250d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int enableNative(); 2251d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int disableNative(); 2252d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2253d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native Object[] getAdapterPropertiesNative(); 2254d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native Object[] getDevicePropertiesNative(String objectPath); 2255d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyStringNative(String key, String value); 2256d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyIntegerNative(String key, int value); 2257d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyBooleanNative(String key, int value); 2258d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2259d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean startDiscoveryNative(); 2260d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean stopDiscoveryNative(); 2261d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2262d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean createPairedDeviceNative(String address, int timeout_ms); 2263d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean cancelDeviceCreationNative(String address); 2264d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean removeDeviceNative(String objectPath); 2265d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int getDeviceServiceChannelNative(String objectPath, String uuid, 2266d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh int attributeId); 2267d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2268b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean cancelPairingUserInputNative(String address, int nativeData); 2269d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setPinNative(String address, String pin, int nativeData); 2270b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPasskeyNative(String address, int passkey, int nativeData); 2271b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPairingConfirmationNative(String address, boolean confirm, 2272b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh int nativeData); 227324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean setDevicePropertyBooleanNative(String objectPath, String key, 227424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int value); 22751caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private native boolean createDeviceNative(String address); 227616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ native boolean discoverServicesNative(String objectPath, String pattern); 227710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 227824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb, 227924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly short channel); 228024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean removeServiceRecordNative(int handle); 2281b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh private native boolean setLinkTimeoutNative(String path, int num_slots); 2282545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh private native boolean connectInputDeviceNative(String path); 2283545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh private native boolean disconnectInputDeviceNative(String path); 22849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2285