BluetoothService.java revision cc2c06656ceafbcd91ec5b679aa6c9eae0d9982c
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 2730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganeshimport com.android.internal.app.IBatteryStats; 2830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 29bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.BluetoothAdapter; 30dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganeshimport android.bluetooth.BluetoothClass; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothDevice; 32f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganeshimport android.bluetooth.BluetoothDeviceProfileState; 335a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport android.bluetooth.BluetoothHeadset; 344ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganeshimport android.bluetooth.BluetoothInputDevice; 356fdd0c6274c81b337ad35b70480f881daf7354c3Danica Changimport android.bluetooth.BluetoothPan; 3696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganeshimport android.bluetooth.BluetoothProfile; 37f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganeshimport android.bluetooth.BluetoothProfileState; 3824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pellyimport android.bluetooth.BluetoothSocket; 3910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganeshimport android.bluetooth.BluetoothUuid; 40bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.IBluetooth; 4116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport android.bluetooth.IBluetoothCallback; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 476e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganeshimport android.content.SharedPreferences; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 503fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.IBinder; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 523fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.ParcelUuid; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 54105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.os.ServiceManager; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 57cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganeshimport android.util.Pair; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedInputStream; 603fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedWriter; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileInputStream; 633fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileNotFoundException; 643fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileWriter; 653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.IOException; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.UnsupportedEncodingException; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 7116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport java.util.Iterator; 725a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 75bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellypublic class BluetoothService extends IBluetooth.Stub { 76bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private static final String TAG = "BluetoothService"; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean DBG = true; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNativeData; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BluetoothEventLoop mEventLoop; 8196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh private BluetoothHeadset mBluetoothHeadset; 824ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh private BluetoothInputDevice mInputDevice; 8374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private BluetoothPan mPan; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsAirplaneSensitive; 8544303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey private boolean mIsAirplaneToggleable; 86105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private int mBluetoothState; 87997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly private boolean mRestart = false; // need to call enable() after disable() 88bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private boolean mIsDiscovering; 8984690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private int[] mAdapterSdpHandles; 9050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private ParcelUuid[] mAdapterUuids; 91997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 92bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private BluetoothAdapter mAdapter; // constant after init() 939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothBondState mBondState; // local cache of bondings 94105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private final IBatteryStats mBatteryStats; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 98a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1003fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_ADDRESS_PATH = "/sys/class/switch/dock/bt_addr"; 1013fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_PIN_PATH = "/sys/class/switch/dock/bt_pin"; 1023fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1036e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address"; 1046e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings"; 1056e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 10684690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private static final int MESSAGE_FINISH_DISABLE = 1; 10784690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private static final int MESSAGE_UUID_INTENT = 2; 108fbb238db719cbae98afcb897f509b02edf58b062Jaikumar Ganesh private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3; 109a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 110a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // The time (in millisecs) to delay the pairing attempt after the first 111a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // auto pairing attempt fails. We use an exponential delay with 112a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and 113a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value. 114a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000; 115a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000; 1161caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 1171caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // The timeout used to sent the UUIDs Intent 1181caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // This timeout should be greater than the page timeout 1191caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private static final int UUID_INTENT_DELAY = 6000; 120105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 12116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** Always retrieve RFCOMM channel for these SDP UUIDs */ 12216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static final ParcelUuid[] RFCOMM_UUIDS = { 12316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.Handsfree, 12416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.HSP, 12516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.ObexObjectPush }; 12616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothAdapterProperties mAdapterProperties; 1289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothDeviceProperties mDeviceProperties; 129d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 13016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache; 13116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final ArrayList<String> mUuidIntentTracker; 13216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker; 1331caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 13424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private final HashMap<Integer, Integer> mServiceRecordToPid; 13524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 136f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState; 137f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final BluetoothProfileState mA2dpProfileState; 138f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final BluetoothProfileState mHfpProfileState; 1399b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 1409b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private BluetoothA2dpService mA2dpService; 141cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData; 142545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 143a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh private int mProfilesConnected = 0, mProfilesConnecting = 0, mProfilesDisconnecting = 0; 144707952ecd4b6cae25aabcf51f94d702a65847e9eJaikumar Ganesh 1453fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static String mDockAddress; 1463fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private String mDockPin; 1473fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 148c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED; 149a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh private BluetoothPanProfileHandler mBluetoothPanProfileHandler; 15030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh private BluetoothInputProfileHandler mBluetoothInputProfileHandler; 151c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 15216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static class RemoteService { 15316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public String address; 15416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public ParcelUuid uuid; 15516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public RemoteService(String address, ParcelUuid uuid) { 15616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.address = address; 15716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.uuid = uuid; 15816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 15916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly @Override 16016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public boolean equals(Object o) { 16116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (o instanceof RemoteService) { 16216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = (RemoteService)o; 16316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return address.equals(service.address) && uuid.equals(service.uuid); 16416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 16516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 16616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 1675f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root 1685f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root @Override 1695f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root public int hashCode() { 1705f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root int hash = 1; 1715f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (address == null ? 0 : address.hashCode()); 1725f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (uuid == null ? 0 : uuid.hashCode()); 1735f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root return hash; 1745f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root } 17516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 17616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project classInitNative(); 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 181bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public BluetoothService(Context context) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 183105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 184105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Need to do this in place of: 185105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // mBatteryStats = BatteryStatsService.getService(); 186105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Since we can not import BatteryStatsService from here. This class really needs to be 187105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // moved to java/services/com/android/server/ 188105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initializeNativeDataNative(); 191ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 192ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (isEnabledNative() == 1) { 193ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Log.w(TAG, "Bluetooth daemons already running - runtime restart? "); 194ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project disableNative(); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 196ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 197de893f550301a60274e87aa8168225e7a7a42184Nick Pelly mBluetoothState = BluetoothAdapter.STATE_OFF; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsDiscovering = false; 199a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh 2009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mBondState = new BluetoothBondState(context, this); 2019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mAdapterProperties = new BluetoothAdapterProperties(context, this); 2029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties = new BluetoothDeviceProperties(this); 20310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 20410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>(); 205cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mDeviceOobData = new HashMap<String, Pair<byte[], byte[]>>(); 2061caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker = new ArrayList<String>(); 20716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>(); 20824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid = new HashMap<Integer, Integer>(); 209f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>(); 210f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP); 211f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP); 212f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh 213f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.start(); 214f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.start(); 2153fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2163fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh IntentFilter filter = new IntentFilter(); 2176e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh registerForAirplaneMode(filter); 2186e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 2193fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh filter.addAction(Intent.ACTION_DOCK_EVENT); 2206e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.registerReceiver(mReceiver, filter); 22130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this); 222a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this); 2233fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2243fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2259b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public static synchronized String readDockBluetoothAddress() { 2263fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (mDockAddress != null) return mDockAddress; 2273fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2283fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedInputStream file = null; 2293fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh String dockAddress; 2303fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2313fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file = new BufferedInputStream(new FileInputStream(DOCK_ADDRESS_PATH)); 2323fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh byte[] address = new byte[17]; 2333fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.read(address); 2343fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = new String(address); 2353fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = dockAddress.toUpperCase(); 2363fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (BluetoothAdapter.checkBluetoothAddress(dockAddress)) { 2373fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = dockAddress; 2383fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockAddress; 2393fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } else { 2409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "CheckBluetoothAddress failed for car dock address: " 2419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + dockAddress); 2423fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2433fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "FileNotFoundException while trying to read dock address"); 2453fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "IOException while trying to read dock address"); 2473fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 2483fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (file != null) { 2493fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2503fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.close(); 2513fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2523fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 2533fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2553fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2563fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = null; 2573fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return null; 2583fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2603fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private synchronized boolean writeDockPin() { 2613fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedWriter out = null; 2623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2633fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out = new BufferedWriter(new FileWriter(DOCK_PIN_PATH)); 2643fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Generate a random 4 digit pin between 0000 and 9999 2663fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // This is not truly random but good enough for our purposes. 2673fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh int pin = (int) Math.floor(Math.random() * 10000); 2683fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = String.format("%04d", pin); 2703fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.write(mDockPin); 2713fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return true; 2723fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2739a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "FileNotFoundException while trying to write dock pairing pin"); 2743fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2759a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "IOException while while trying to write dock pairing pin"); 2763fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 2773fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (out != null) { 2783fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2793fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.close(); 2803fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2813fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 2823fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2833fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2843fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2853fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = null; 2863fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 2873fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2883fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2893fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh /*package*/ synchronized String getDockPin() { 2903fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockPin; 291bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly } 292bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly 293bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public synchronized void initAfterRegistration() { 294f242b7b931898856bcbcb7ec36cacf43098ba544Nick Pelly mAdapter = BluetoothAdapter.getDefaultAdapter(); 295bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mEventLoop = new BluetoothEventLoop(mContext, mAdapter, this); 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2987d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh public synchronized void initAfterA2dpRegistration() { 2997d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh mEventLoop.getProfileProxy(); 3007d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh } 3017d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 3046e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.unregisterReceiver(mReceiver); 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cleanupNativeDataNative(); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isEnabled() { 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 3148c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh return isEnabledInternal(); 3158c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh } 3168c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 3178c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh private boolean isEnabledInternal() { 318de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return mBluetoothState == BluetoothAdapter.STATE_ON; 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 321105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public int getBluetoothState() { 322105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 323105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return mBluetoothState; 324105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 325105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int getBluetoothStateInternal() { 3279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mBluetoothState; 3289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 329105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth and disable BT in settings. Returns true on success. 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean disable() { 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return disable(true); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth. Returns true on success. 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 340e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly * @param saveSetting If true, persist the new setting 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean disable(boolean saveSetting) { 343e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 345105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project switch (mBluetoothState) { 346de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_OFF: 347105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 348de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_ON: 349105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 350105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project default: 351105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return false; 352105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEnableThread != null && mEnableThread.isAlive()) { 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35684690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh 357de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF); 35884690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh 35984690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles); 36074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh setBluetoothTetheringNative(false, BluetoothPanProfileHandler.NAP_ROLE, 36174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothPanProfileHandler.NAP_BRIDGE); 362105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 363105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Allow 3 seconds for profiles to gracefully disconnect 364105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // TODO: Introduce a callback mechanism so that each profile can notify 365bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly // BluetoothService when it is done shutting down 3667a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh disconnectDevices(); 3677a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh 368105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mHandler.sendMessageDelayed( 369105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000); 370105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 371105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 372105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3737a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh private synchronized void disconnectDevices() { 3747a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh // Disconnect devices handled by BluetoothService. 3757a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh for (BluetoothDevice device: getConnectedInputDevices()) { 3767a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh disconnectInputDevice(device); 3777a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 3787a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh 3797a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh for (BluetoothDevice device: getConnectedPanDevices()) { 3807a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh disconnectPanDevice(device); 3817a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 3827a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 383105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 384105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private synchronized void finishDisable(boolean saveSetting) { 385de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_TURNING_OFF) { 386105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEventLoop.stop(); 389d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh tearDownNativeDataNative(); 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project disableNative(); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mark in progress bondings as cancelled 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) { 394005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3982d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh // Stop the profile state machine for bonded devices. 3992d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDED)) { 4002d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh removeProfileState(address); 4012d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh } 4022d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // update mode 404de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 405de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE); 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 408105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mIsDiscovering = false; 409bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.clear(); 41024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.clear(); 411105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 412a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnected = 0; 413a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnecting = 0; 414a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesDisconnecting = 0; 415c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED; 41650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids = null; 41750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterSdpHandles = null; 418a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (saveSetting) { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project persistBluetoothOnSetting(false); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 422105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 423de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_OFF); 424105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 425105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Log bluetooth off to battery stats. 426105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project long ident = Binder.clearCallingIdentity(); 427105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project try { 428105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats.noteBluetoothOff(); 429105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } catch (RemoteException e) { 430105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } finally { 431105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Binder.restoreCallingIdentity(ident); 432105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 433997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 434997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (mRestart) { 435997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 436997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly enable(); 437997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 440105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /** Bring up BT and persist BT on in settings */ 441105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public boolean enable() { 442105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return enable(true); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enable this Bluetooth device, asynchronously. 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This turns on/off the underlying hardware. 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 449105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @param saveSetting If true, persist the new state of BT in settings 450105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @return True on success (so far) 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 452105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public synchronized boolean enable(boolean saveSetting) { 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Airplane mode can prevent Bluetooth radio from being turned on. 45744303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 460de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_OFF) { 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEnableThread != null && mEnableThread.isAlive()) { 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 466de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_TURNING_ON); 467105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mEnableThread = new EnableThread(saveSetting); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEnableThread.start(); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 472997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /** Forcibly restart Bluetooth if it is on */ 473997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /* package */ synchronized void restart() { 474de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_ON) { 475997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly return; 476997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 477997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = true; 478997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (!disable(false)) { 479997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 480997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 481d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 482997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 483105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private synchronized void setBluetoothState(int state) { 484105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (state == mBluetoothState) { 485105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 486105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 487105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 4889a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Bluetooth state " + mBluetoothState + " -> " + state); 489105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 490de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 491de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mBluetoothState); 492de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_STATE, state); 493105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 494105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 495105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBluetoothState = state; 496105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 497105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 498105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 499105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Handler mHandler = new Handler() { 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 504105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case MESSAGE_FINISH_DISABLE: 505105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project finishDisable(msg.arg1 != 0); 506105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 5071caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh case MESSAGE_UUID_INTENT: 5081caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String address = (String)msg.obj; 50916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (address != null) { 5101caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh sendUuidIntent(address); 51116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly makeServiceChannelCallbacks(address); 51216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 5131caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh break; 514a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY: 515a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh address = (String)msg.obj; 516a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (address != null) { 517a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh createBond(address); 518a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 519a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 520a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh break; 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private EnableThread mEnableThread; 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class EnableThread extends Thread { 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean mSaveSetting; 529105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public EnableThread(boolean saveSetting) { 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSaveSetting = saveSetting; 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean res = (enableNative() == 0); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res) { 535b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project int retryCount = 2; 536b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project boolean running = false; 537b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project while ((retryCount-- > 0) && !running) { 538b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mEventLoop.start(); 5399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // it may take a moment for the other thread to do its 540b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // thing. Check periodically for a while. 541b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project int pollCount = 5; 542b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project while ((pollCount-- > 0) && !running) { 543b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (mEventLoop.isEventLoopRunning()) { 544b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project running = true; 545b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project break; 546b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 547b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project try { 548b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project Thread.sleep(100); 549b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } catch (InterruptedException e) {} 550b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 551b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 552b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (!running) { 5539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "bt EnableThread giving up"); 554b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project res = false; 555b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project disableNative(); 556b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res) { 560d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!setupNativeDataNative()) { 561d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return; 562d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSaveSetting) { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project persistBluetoothOnSetting(true); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 56684690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh 56784690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh mIsDiscovering = false; 56884690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh mBondState.readAutoPairingData(); 56984690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh mBondState.loadBondState(); 57084690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh initProfileState(); 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5729efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh // This should be the last step of the the enable thread. 5739efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh // Because this adds SDP records which asynchronously 5749efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh // broadcasts the Bluetooth On State in updateBluetoothState. 5759efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh // So we want all internal state setup before this. 5769efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh updateSdpRecords(); 57750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } else { 57850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh setBluetoothState(BluetoothAdapter.STATE_OFF); 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 580105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mEnableThread = null; 58150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 58250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 583105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 58450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) { 58550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh //Register SDP records. 58650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh int[] svcIdentifiers = new int[uuids.size()]; 58750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh for (int i = 0; i < uuids.size(); i++) { 58850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh svcIdentifiers[i] = BluetoothUuid.getServiceIdentifierFromParcelUuid(uuids.get(i)); 58950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 59050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterSdpHandles = addReservedServiceRecordsNative(svcIdentifiers); 59150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 592105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 59350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private synchronized void updateSdpRecords() { 59450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh ArrayList<ParcelUuid> uuids = new ArrayList<ParcelUuid>(); 59550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 59650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add the default records 59750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.HSP_AG); 59850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.ObexObjectPush); 59950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 60050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh if (mContext.getResources(). 60150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh getBoolean(com.android.internal.R.bool.config_voice_capable)) { 60250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.Handsfree_AG); 60350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.PBAP_PSE); 60450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 60550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 60650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add SDP records for profiles maintained by Android userspace 60750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh addReservedSdpRecords(uuids); 60850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 60950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Enable profiles maintained by Bluez userspace. 61074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE, 61174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothPanProfileHandler.NAP_BRIDGE); 61250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 61350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add SDP records for profiles maintained by Bluez userspace 61450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.AudioSource); 61550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.AvrcpTarget); 61650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.NAP); 61750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 61850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Cannot cast uuids.toArray directly since ParcelUuid is parcelable 61950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids = new ParcelUuid[uuids.size()]; 62050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh for (int i = 0; i < uuids.size(); i++) { 62150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids[i] = uuids.get(i); 62250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 62350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 62450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 6259efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh /** 6269efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * This function is called from Bluetooth Event Loop when onPropertyChanged 6279efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * for adapter comes in with UUID property. 6289efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * @param uuidsThe uuids of adapter as reported by Bluez. 6299efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh */ 63050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh synchronized void updateBluetoothState(String uuids) { 63150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh if (mBluetoothState == BluetoothAdapter.STATE_TURNING_ON) { 63250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids); 63350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 63450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh if (mAdapterUuids != null && 63550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) { 63650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh setBluetoothState(BluetoothAdapter.STATE_ON); 6379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby autoConnect(); 638d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String[] propVal = {"Pairable", getProperty("Pairable")}; 639d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mEventLoop.onPropertyChanged(propVal); 640b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 6419efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh // Log bluetooth on to battery stats. 6429efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh long ident = Binder.clearCallingIdentity(); 6439efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh try { 6449efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh mBatteryStats.noteBluetoothOn(); 6459efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh } catch (RemoteException e) { 6469efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh } finally { 6479efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh Binder.restoreCallingIdentity(ident); 6489efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh } 6499efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh 65050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 65150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh disable(false); 65250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 6535c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa } 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void persistBluetoothOnSetting(boolean bluetoothOn) { 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long origCallerIdentityToken = Binder.clearCallingIdentity(); 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON, 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bluetoothOn ? 1 : 0); 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(origCallerIdentityToken); 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 664a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean attemptAutoPair(String address) { 665a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (!mBondState.hasAutoPairingFailed(address) && 666a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh !mBondState.isAutoPairingBlacklisted(address)) { 667a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.attempt(address); 668a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setPin(address, BluetoothDevice.convertPinToBytes("0000")); 669a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return true; 670a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 671a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return false; 672a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 673a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 674f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh /*package*/ synchronized boolean isFixedPinZerosAutoPairKeyboard(String address) { 675f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh // Check for keyboards which have fixed PIN 0000 as the pairing pin 676f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh return mBondState.isFixedPinZerosAutoPairKeyboard(address); 677f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh } 678f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh 679a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized void onCreatePairedDeviceResult(String address, int result) { 680a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (result == BluetoothDevice.BOND_SUCCESS) { 681a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_BONDED); 682a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (mBondState.isAutoPairingAttemptsInProgress(address)) { 683a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 684a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 685a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED && 686a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.getAttempt(address) == 1) { 687a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.addAutoPairingFailure(address); 688a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh pairingAttempt(address, result); 689a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN && 690a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.isAutoPairingAttemptsInProgress(address)) { 691a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh pairingAttempt(address, result); 692a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else { 693a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_NONE, result); 694a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (mBondState.isAutoPairingAttemptsInProgress(address)) { 695a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 696a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 697a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 698a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 699a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 700a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized String getPendingOutgoingBonding() { 701a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return mBondState.getPendingOutgoingBonding(); 702a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 703a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 704a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private void pairingAttempt(String address, int result) { 705a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // This happens when our initial guess of "0000" as the pass key 706a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // fails. Try to create the bond again and display the pin dialog 707a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // to the user. Use back-off while posting the delayed 708a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // message. The initial value is 709a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is 710a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is 711a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // reached, display an error to the user. 712a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh int attempt = mBondState.getAttempt(address); 713a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY > 714a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) { 715a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 716a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_NONE, result); 717a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 718a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 719a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 720a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh Message message = mHandler.obtainMessage(MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); 721a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh message.obj = address; 722a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh boolean postResult = mHandler.sendMessageDelayed(message, 723a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); 724a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (!postResult) { 725a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 726a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, 727a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh BluetoothDevice.BOND_NONE, result); 728a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 729a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 730a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.attempt(address); 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ BluetoothDevice getRemoteDevice(String address) { 7349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapter.getRemoteDevice(address); 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String toBondStateString(int bondState) { 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (bondState) { 739005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly case BluetoothDevice.BOND_NONE: 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "not bonded"; 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDING: 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonding"; 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDED: 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonded"; 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "??????"; 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setName(String name) { 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == null) { 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 756d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyString("Name", name); 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh //TODO(): setPropertyString, setPropertyInteger, setPropertyBoolean 760d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Either have a single property function with Object as the parameter 761d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // or have a function for each property and then obfuscate in the JNI layer. 762d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The following looks dirty. 763d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyString(String key, String value) { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 7658c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 766d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyStringNative(key, value); 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyInteger(String key, int value) { 770d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 7718c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 772d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyIntegerNative(key, value); 773d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 775d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyBoolean(String key, boolean value) { 776d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 7778c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 778d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyBooleanNative(key, value ? 1 : 0); 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 781d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /** 782d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Set the discoverability window for the device. A timeout of zero 783d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * makes the device permanently discoverable (if the device is 784d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * discoverable). Setting the timeout to a nonzero value does not make 785d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * a device discoverable; you need to call setMode() to make the device 786d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * explicitly discoverable. 787d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 788f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby * @param timeout The discoverable timeout in seconds. 789d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh */ 790d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean setDiscoverableTimeout(int timeout) { 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 793d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyInteger("DiscoverableTimeout", timeout); 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 79612835478ee687a493d1b5882e67b6725bd539c26Nick Pelly public synchronized boolean setScanMode(int mode, int duration) { 79718b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, 79818b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly "Need WRITE_SECURE_SETTINGS permission"); 7999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean pairable; 8009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean discoverable; 80112835478ee687a493d1b5882e67b6725bd539c26Nick Pelly 802de893f550301a60274e87aa8168225e7a7a42184Nick Pelly switch (mode) { 803de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 804d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = false; 805d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 806de893f550301a60274e87aa8168225e7a7a42184Nick Pelly break; 807de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 808d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 809d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 810005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 811de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 812d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 813d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = true; 81412835478ee687a493d1b5882e67b6725bd539c26Nick Pelly if (DBG) Log.d(TAG, "BT Discoverable for " + duration + " seconds"); 815005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 816de893f550301a60274e87aa8168225e7a7a42184Nick Pelly default: 817de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Log.w(TAG, "Requested invalid scan mode " + mode); 818de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return false; 819d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 820d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh setPropertyBoolean("Pairable", pairable); 821d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh setPropertyBoolean("Discoverable", discoverable); 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 823d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return true; 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 826b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh /*package*/ synchronized String getProperty(String name) { 827b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh if (!isEnabledInternal()) return null; 8289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapterProperties.getProperty(name); 829b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh } 830b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh 8319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothAdapterProperties getAdapterProperties() { 8329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapterProperties; 8339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDeviceProperties getDeviceProperties() { 8369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties; 8379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean isRemoteDeviceInCache(String address) { 8409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties.isInCache(address); 8419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void setRemoteDeviceProperty(String address, String name, String value) { 8449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties.setProperty(address, name, value); 8459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void updateRemoteDevicePropertiesCache(String address) { 8489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties.updateCache(address); 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 851d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getAddress() { 852d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 853d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Address"); 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 856d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getName() { 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 858d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Name"); 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 86158b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh public synchronized ParcelUuid[] getUuids() { 86258b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 86358b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh String value = getProperty("UUIDs"); 86458b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh if (value == null) return null; 86550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh return convertStringToParcelUuid(value); 86650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 86758b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 86850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private synchronized ParcelUuid[] convertStringToParcelUuid(String value) { 86958b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh String[] uuidStrings = null; 87058b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh // The UUIDs are stored as a "," separated string. 87158b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh uuidStrings = value.split(","); 87258b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; 87358b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 87458b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh for (int i = 0; i < uuidStrings.length; i++) { 87558b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh uuids[i] = ParcelUuid.fromString(uuidStrings[i]); 87658b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh } 87758b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh return uuids; 87858b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh } 87958b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 88058b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 882d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Returns the user-friendly name of a remote device. This value is 883d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * returned from our local cache, which is updated when onPropertyChange 884d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * event is received. 885d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Do not expect to retrieve the updated remote name immediately after 886d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * changing the name on the remote device. 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 888d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Bluetooth address of remote device. 889d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 890d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return The user-friendly name of the specified remote device. 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 892d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getRemoteName(String address) { 893d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 894005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 895d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 896d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 8979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties.getProperty(address, "Name"); 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the discoverability window for the device. A timeout of zero 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * means that the device is permanently discoverable (if the device is 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the discoverable mode). 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The discoverability window of the device, in seconds. A negative 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value indicates an error. 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getDiscoverableTimeout() { 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 910d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String timeout = getProperty("DiscoverableTimeout"); 911d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (timeout != null) 912d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(timeout); 913d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 914d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return -1; 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getScanMode() { 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 9198c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) 920de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 921d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 922d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean pairable = getProperty("Pairable").equals("true"); 923d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean discoverable = getProperty("Discoverable").equals("true"); 924d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return bluezStringToScanMode (pairable, discoverable); 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 927d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean startDiscovery() { 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9308c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 9318c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 932d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return startDiscoveryNative(); 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 935d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean cancelDiscovery() { 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9388c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 9398c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 940d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return stopDiscoveryNative(); 941d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 942d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 943d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean isDiscovering() { 944d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 945d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return mIsDiscovering; 946d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 947d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 948d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ void setIsDiscovering(boolean isDiscovering) { 949d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mIsDiscovering = isDiscovering; 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 952cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private boolean isBondingFeasible(String address) { 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9558c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 9568c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 957005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9622092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (mBondState.getPendingOutgoingBonding() != null) { 9639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Ignoring createBond(): another device is bonding"); 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a different device is currently bonding, fail 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check for bond state only if we are not performing auto 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pairing exponential back-off attempts. 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mBondState.isAutoPairingAttemptsInProgress(address) && 971005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.getBondState(address) != BluetoothDevice.BOND_NONE) { 9729a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Ignoring createBond(): this device is already bonding or bonded"); 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9763fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (address.equals(mDockAddress)) { 9773fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (!writeDockPin()) { 9789a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "Error while writing Pin for the dock"); 9793fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 9803fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 9813fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 982cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return true; 983cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 9843fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 985cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean createBond(String address) { 986cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isBondingFeasible(address)) return false; 987cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 988cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!createPairedDeviceNative(address, 60000 /*1 minute*/ )) { 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9922092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mBondState.setPendingOutgoingBonding(address); 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); 9942092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 998cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean createBondOutOfBand(String address, byte[] hash, 999cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer) { 1000cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isBondingFeasible(address)) return false; 10013fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1002cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!createPairedDeviceOutOfBandNative(address, 60000 /* 1 minute */)) { 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1006cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh setDeviceOutOfBandData(address, hash, randomizer); 10072092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mBondState.setPendingOutgoingBonding(address); 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); 10092092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1013cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean setDeviceOutOfBandData(String address, byte[] hash, 1014cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer) { 1015cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1016cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 1017cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return false; 1018cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1019cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair <byte[], byte[]> value = new Pair<byte[], byte[]>(hash, randomizer); 1020cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1021cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (DBG) { 10229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Setting out of band data for: " + address + ":" + 10239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Arrays.toString(hash) + ":" + Arrays.toString(randomizer)); 1024cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1025cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1026cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mDeviceOobData.put(address, value); 1027cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return true; 1028cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1029cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1030cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair<byte[], byte[]> getDeviceOutOfBandData(BluetoothDevice device) { 1031cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return mDeviceOobData.get(device.getAddress()); 1032cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1033cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1034cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1035cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized byte[] readOutOfBandData() { 1036cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1037cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH permission"); 1038cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return null; 1039cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1040cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return readAdapterOutOfBandDataNative(); 1041cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1042cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean cancelBondProcess(String address) { 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 10468c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 10478c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1048005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) { 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1056005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 1058d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh cancelDeviceCreationNative(address); 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean removeBond(String address) { 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 10658c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 10668c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1067005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1070f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 10719b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 1072f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh state.sendMessage(BluetoothDeviceProfileState.UNPAIR); 10739b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 10749b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } else { 10759b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 10769b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 10779b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 10789b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 10799b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public synchronized boolean removeBondInternal(String address) { 1080cc2c06656ceafbcd91ec5b679aa6c9eae0d9982cJaikumar Ganesh // Unset the trusted device state and then unpair 1081cc2c06656ceafbcd91ec5b679aa6c9eae0d9982cJaikumar Ganesh setTrust(address, false); 1082d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return removeDeviceNative(getObjectPathFromAddress(address)); 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized String[] listBonds() { 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.listInState(BluetoothDevice.BOND_BONDED); 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1090a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized String[] listInState(int state) { 1091a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return mBondState.listInState(state); 1092a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1093a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getBondState(String address) { 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1096005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1097b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.getBondState(address.toUpperCase()); 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1102a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean setBondState(String address, int state) { 1103a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return setBondState(address, state, 0); 1104a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1105a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 1106a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean setBondState(String address, int state, int reason) { 1107a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.setBondState(address.toUpperCase(), state); 1108a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return true; 1109a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1110a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 11113fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh public synchronized boolean isBluetoothDock(String address) { 11126e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 11139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Context.MODE_PRIVATE); 11146e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 11156e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh return sp.contains(SHARED_PREFERENCE_DOCK_ADDRESS + address); 11163fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 11173fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 11189488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh /*package*/ String[] getRemoteDeviceProperties(String address) { 11198c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return null; 11208c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 11219488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh String objectPath = getObjectPathFromAddress(address); 11229488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh return (String [])getDevicePropertiesNative(objectPath); 11239488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 11249488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1126efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Sets the remote device trust state. 1127efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 1128efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * @return boolean to indicate operation success or fail 1129efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1130efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean setTrust(String address, boolean value) { 1131005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1132e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1133e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly "Need BLUETOOTH_ADMIN permission"); 1134efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1135efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1136efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 11378c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11388c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 11399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return setDevicePropertyBooleanNative( 11409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby getObjectPathFromAddress(address), "Trusted", value ? 1 : 0); 1141efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1142efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1143efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1144efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Gets the remote device trust state as boolean. 1145efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Note: this value may be 1146efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * retrieved from cache if we retrieved the data before * 1147efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 11489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @return boolean to indicate trusted or untrusted state 1149efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1150efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean getTrustState(String address) { 1151005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1152efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1153efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1154efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1155efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 11569a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = mDeviceProperties.getProperty(address, "Trusted"); 1157efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue if (val == null) { 1158efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1159efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } else { 11609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return val.equals("true"); 1161efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1162efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1163efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1164efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1165d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the remote major, minor classes encoded as a 32-bit 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * integer. 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: this value is retrieved from cache, because we get it during 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * remote-device discovery. 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return 32-bit integer encoding the remote major, minor, and service 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * classes. 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getRemoteClass(String address) { 1175005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1176ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1177ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly return BluetoothClass.ERROR; 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11799a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = mDeviceProperties.getProperty(address, "Class"); 1180d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (val == null) 1181d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return BluetoothClass.ERROR; 1182d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else { 1183d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(val); 1184d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1186d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1189dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * Gets the UUIDs supported by the remote device 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1191dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @return array of 128bit ParcelUuids 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1193dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public synchronized ParcelUuid[] getRemoteUuids(String address) { 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1195005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11981caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return getUuidFromCache(address); 11991caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12001caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid[] getUuidFromCache(String address) { 12029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String value = mDeviceProperties.getProperty(address, "UUIDs"); 1203dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh if (value == null) return null; 1204dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1205dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh String[] uuidStrings = null; 1206d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The UUIDs are stored as a "," separated string. 1207dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuidStrings = value.split(","); 1208dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; 1209dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1210dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh for (int i = 0; i < uuidStrings.length; i++) { 1211dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuids[i] = ParcelUuid.fromString(uuidStrings[i]); 1212dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh } 1213d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return uuids; 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 121616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** 121716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Connect and fetch new UUID's using SDP. 121816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * The UUID's found are broadcast as intents. 121916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Optionally takes a uuid and callback to fetch the RFCOMM channel for the 122016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * a given uuid. 122116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to broadcast UUID intents on success 122216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to handle the failure case for 122316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * callback and broadcast intents. 122416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly */ 122516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public synchronized boolean fetchRemoteUuids(String address, ParcelUuid uuid, 122616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback) { 12271caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 12288c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 12298c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 12301caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (!BluetoothAdapter.checkBluetoothAddress(address)) { 12311caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return false; 12321caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12331caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 123416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = new RemoteService(address, uuid); 123516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null && mUuidCallbackTracker.get(service) != null) { 123616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // An SDP query for this address & uuid is already in progress 123716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Do not add this callback for the uuid 123816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 123916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 124016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 12411caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (mUuidIntentTracker.contains(address)) { 12421caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // An SDP query for this address is already in progress 124316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Add this uuid onto the in-progress SDP query 124416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 124516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 124616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 12471caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return true; 12481caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12491caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12501caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh boolean ret; 12510e09030977aea8b40fd177139528d4b5637c9771Jaikumar Ganesh // Just do the SDP if the device is already created and UUIDs are not 12520e09030977aea8b40fd177139528d4b5637c9771Jaikumar Ganesh // NULL, else create the device and then do SDP. 12539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (mDeviceProperties.isInCache(address) && getRemoteUuids(address) != null) { 12541caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String path = getObjectPathFromAddress(address); 12551caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (path == null) return false; 12561caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12571caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // Use an empty string for the UUID pattern 12581caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh ret = discoverServicesNative(path, ""); 12591caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } else { 12601caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh ret = createDeviceNative(address); 12611caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12621caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12631caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker.add(address); 126416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 126516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 126616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 12671caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12681caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT); 12691caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh message.obj = address; 12701caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY); 12711caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return ret; 12721caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12731caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1275d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the rfcomm channel associated with the UUID. 127616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Pulls records from the cache only. 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1278d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Address of the remote device 1279dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @param uuid ParcelUuid of the service attribute 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1281d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return rfcomm channel associated with the service attribute 128210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh * -1 on error 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1284dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public int getRemoteServiceChannel(String address, ParcelUuid uuid) { 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 12868c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 12878c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1288005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1289b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 129110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // Check if we are recovering from a crash. 129210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (mDeviceProperties.isEmpty()) { 12939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (mDeviceProperties.updateCache(address) == null) 129410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 129510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 129610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 129710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address); 129810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (value != null && value.containsKey(uuid)) 129910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return value.get(uuid); 130010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setPin(String address, byte[] pin) { 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 13068c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13078c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pin == null || pin.length <= 0 || pin.length > 16 || 1309005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly !BluetoothAdapter.checkBluetoothAddress(address)) { 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "setPin(" + address + ") called but no native data available, " + 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " or by bluez.\n"); 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bluez API wants pin as a string 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pinString; 13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pinString = new String(pin, "UTF8"); 13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (UnsupportedEncodingException uee) { 13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "UTF8 not supported?!?"); 13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return setPinNative(address, pinString, data.intValue()); 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1331b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPasskey(String address, int passkey) { 1332b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1333b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 13348c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13358c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1336005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (passkey < 0 || passkey > 999999 || !BluetoothAdapter.checkBluetoothAddress(address)) { 1337b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1338b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1339b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1340b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1341b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1342b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1343b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1344b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1345b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1346b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1347b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPasskeyNative(address, passkey, data.intValue()); 1348b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1349b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1350b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPairingConfirmation(String address, boolean confirm) { 1351b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1352b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 13538c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13548c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1355b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1356b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1357b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1358b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1359b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1360b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1361b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1362b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1363b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPairingConfirmationNative(address, confirm, data.intValue()); 1364b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1365b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1366cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean setRemoteOutOfBandData(String address) { 1367cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1368cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 1369cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return false; 1370cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh address = address.toUpperCase(); 1371cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1372cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (data == null) { 1373cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Log.w(TAG, "setRemoteOobData(" + address + ") called but no native data available, " + 1374cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1375cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh " or by bluez.\n"); 1376cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return false; 1377cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1378cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1379cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair<byte[], byte[]> val = mDeviceOobData.get(address); 1380cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] hash, randomizer; 1381cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (val == null) { 1382cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh // TODO: check what should be passed in this case. 1383cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh hash = new byte[16]; 1384cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh randomizer = new byte[16]; 1385cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } else { 1386cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh hash = val.first; 1387cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh randomizer = val.second; 1388cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1389cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return setRemoteOutOfBandDataNative(address, hash, randomizer, data.intValue()); 1390cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1391cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1392b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean cancelPairingUserInput(String address) { 13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 13958c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13968c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1397005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1400005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 1401397d8f4f4829a45f4fe7a672cc395466bbc0f442Jaikumar Ganesh BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 1405b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "cancelUserInputNative(" + address + ") called but no native data " + 1406b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "available, ignoring. Maybe the PasskeyAgent Request was already cancelled " + 1407b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "by the remote or by bluez.\n"); 14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1410b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return cancelPairingUserInputNative(address, data.intValue()); 14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14138c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh /*package*/ void updateDeviceServiceChannelCache(String address) { 14149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "updateDeviceServiceChannelCache(" + address + ")"); 14159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 141610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // We are storing the rfcomm channel numbers only for the uuids 141710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // we are interested in. 14189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid[] deviceUuids = getRemoteUuids(address); 141916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 14209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ArrayList<ParcelUuid> applicationUuids = new ArrayList<ParcelUuid>(); 142116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 142216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 142316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (RemoteService service : mUuidCallbackTracker.keySet()) { 142416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 142516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly applicationUuids.add(service.uuid); 142616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 142716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 142816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 142910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 14309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Map <ParcelUuid, Integer> uuidToChannelMap = new HashMap<ParcelUuid, Integer>(); 143116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 143216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for default uuids 143316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : RFCOMM_UUIDS) { 143410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 14359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = getDeviceServiceChannelForUuid(address, uuid); 14369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuidToChannelMap.put(uuid, channel); 14379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "\tuuid(system): " + uuid + " " + channel); 143810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 143910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 144016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for application requested uuids 144116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : applicationUuids) { 144216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 14439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = getDeviceServiceChannelForUuid(address, uuid); 14449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuidToChannelMap.put(uuid, channel); 14459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "\tuuid(application): " + uuid + " " + channel); 144616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 144716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 144816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 144916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 145016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Make application callbacks 145116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 145216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 145316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 145416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 14559a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (uuidToChannelMap.containsKey(service.uuid)) { 14569a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = uuidToChannelMap.get(service.uuid); 14579a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 14589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Making callback for " + service.uuid + 14599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby " with result " + channel); 146016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 146116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 146216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 146316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(channel); 146416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 146516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 146616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 146716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 146816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 146916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 147016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 147116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 147216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Update cache 14739a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceServiceChannelCache.put(address, uuidToChannelMap); 147416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 147510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 147610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 14779a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private int getDeviceServiceChannelForUuid(String address, 14789a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid uuid) { 14799a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return getDeviceServiceChannelNative(getObjectPathFromAddress(address), 14809a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuid.toString(), 0x0004); 14819a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 14829a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 148324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly /** 148424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * b is a handle to a Binder instance, so that this service can be notified 148524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * for Applications that terminate unexpectedly, to clean there service 148624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * records 148724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly */ 148824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid, 148924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int channel, IBinder b) { 14908c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 14918c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 14928c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 149324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (serviceName == null || uuid == null || channel < 1 || 149424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) { 149524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 149624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 149724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) { 149824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Log.w(TAG, "Attempted to register a reserved UUID: " + uuid); 149924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 150024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 150124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle = addRfcommServiceRecordNative(serviceName, 150224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(), 150324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly (short)channel); 15049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "new handle " + Integer.toHexString(handle)); 150524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (handle == -1) { 150624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 150724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 150824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 150924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int pid = Binder.getCallingPid(); 151024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.put(new Integer(handle), new Integer(pid)); 151124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly try { 151224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly b.linkToDeath(new Reaper(handle, pid), 0); 151324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } catch (RemoteException e) {} 151424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return handle; 151524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 151624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 151724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void removeServiceRecord(int handle) { 151824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 151924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly "Need BLUETOOTH permission"); 152024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly checkAndRemoveRecord(handle, Binder.getCallingPid()); 152124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 152224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 152324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private synchronized void checkAndRemoveRecord(int handle, int pid) { 152424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer handleInt = new Integer(handle); 152524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer owner = mServiceRecordToPid.get(handleInt); 152624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (owner != null && pid == owner.intValue()) { 15279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Removing service record " + 15289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Integer.toHexString(handle) + " for pid " + pid); 152924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.remove(handleInt); 153024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly removeServiceRecordNative(handle); 153124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 153224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 153324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 153424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private class Reaper implements IBinder.DeathRecipient { 153524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int pid; 153624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle; 153724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Reaper(int handle, int pid) { 153824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly this.pid = pid; 153924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly this.handle = handle; 154024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 154124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void binderDied() { 154224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly synchronized (BluetoothService.this) { 15439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Tracked app " + pid + " died"); 154424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly checkAndRemoveRecord(handle, pid); 154524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 154624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 154724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 154824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 15526e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (intent == null) return; 15536e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String action = intent.getAction(); 15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver resolver = context.getContentResolver(); 15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Query the airplane mode from Settings.System just to make sure that 15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // some random app is not sending this intent and disabling bluetooth 15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean enabled = !isAirplaneModeOn(); 15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If bluetooth is currently expected to be on, then enable or disable bluetooth 15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) { 15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (enabled) { 1563105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project enable(false); 15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project disable(false); 15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15686e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else if (Intent.ACTION_DOCK_EVENT.equals(action)) { 15696e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 15706e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh Intent.EXTRA_DOCK_STATE_UNDOCKED); 15716e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (DBG) Log.v(TAG, "Received ACTION_DOCK_EVENT with State:" + state); 15726e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) { 15736e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockAddress = null; 15746e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockPin = null; 15756e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else { 15766e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences.Editor editor = 15776e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 15786e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.MODE_PRIVATE).edit(); 15796e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh editor.putBoolean(SHARED_PREFERENCE_DOCK_ADDRESS + mDockAddress, true); 158066fce5068a8a3aeb28aaf713843891b286a75280Brad Fitzpatrick editor.apply(); 15816e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } 15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15866e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private void registerForAirplaneMode(IntentFilter filter) { 158744303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final ContentResolver resolver = mContext.getContentResolver(); 158844303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String airplaneModeRadios = Settings.System.getString(resolver, 15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_RADIOS); 159044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String toggleableRadios = Settings.System.getString(resolver, 159144303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 159244303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 159344303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneSensitive = airplaneModeRadios == null ? true : 159444303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH); 159544303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneToggleable = toggleableRadios == null ? false : 159644303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH); 159744303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsAirplaneSensitive) { 15996e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Returns true if airplane mode is currently on */ 16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean isAirplaneModeOn() { 16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Settings.System.getInt(mContext.getContentResolver(), 16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_ON, 0) == 1; 16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16091caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /* Broadcast the Uuid intent */ 16101caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /*package*/ synchronized void sendUuidIntent(String address) { 16116179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh ParcelUuid[] uuid = getUuidFromCache(address); 16126179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_UUID); 16132d3b98d868cda30535505b2a2fba47aa1c9c052bJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 16146179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid); 16156179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 16169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mUuidIntentTracker.remove(address); 161716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 161816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 161916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ synchronized void makeServiceChannelCallbacks(String address) { 162016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 162116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 162216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 162316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 16249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Cleaning up failed UUID channel lookup: " 16259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + service.address + " " + service.uuid); 162616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 162716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 162816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 162916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(-1); 163016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 163116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 163216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 163316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 163416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 163516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 16361caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 16371caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 16409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpBluetoothState(pw); 16419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (mBluetoothState != BluetoothAdapter.STATE_ON) { 1642105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1643105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1644105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 164524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive); 164644303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey pw.println("mIsAirplaneToggleable = " + mIsAirplaneToggleable); 164724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 164824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local address = " + getAddress()); 164924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local name = " + getName()); 165024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("isDiscovering() = " + isDiscovering()); 1651105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 165296a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh mAdapter.getProfileProxy(mContext, 165396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.HEADSET); 16544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mAdapter.getProfileProxy(mContext, 16554ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.INPUT_DEVICE); 165674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mAdapter.getProfileProxy(mContext, 165774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.PAN); 1658105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 16599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpKnownDevices(pw); 16609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpAclConnectedDevices(pw); 16619a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpHeadsetService(pw); 16624ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh dumpInputDeviceProfile(pw); 166374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh dumpPanProfile(pw); 16649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpApplicationServiceRecords(pw); 16654ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 16664ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 16679a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpHeadsetService(PrintWriter pw) { 1668105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--Headset Service--"); 166996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (mBluetoothHeadset != null) { 1670bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices(); 1671bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh if (deviceList.size() == 0) { 167274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No headsets connected"); 1673bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh } else { 1674bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 16759a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\ngetConnectedDevices[0] = " + device); 16769a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpHeadsetConnectionState(pw, device); 1677bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh pw.println("getBatteryUsageHint() = " + 1678bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh mBluetoothHeadset.getBatteryUsageHint(device)); 167996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 168096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 16815a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh deviceList.clear(); 16825a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh deviceList = mBluetoothHeadset.getDevicesMatchingConnectionStates(new int[] { 168396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 168474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("--Connected and Disconnected Headsets"); 1685bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 168696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh pw.println(device); 168796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (mBluetoothHeadset.isAudioConnected(device)) { 168896a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh pw.println("SCO audio connected to device:" + device); 168996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 169096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 1691105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 16924ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); 16934ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 16946c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly 16954ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh private void dumpInputDeviceProfile(PrintWriter pw) { 16964ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("\n--Bluetooth Service- Input Device Profile"); 16974ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (mInputDevice != null) { 16984ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh List<BluetoothDevice> deviceList = mInputDevice.getConnectedDevices(); 16994ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (deviceList.size() == 0) { 170074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No input devices connected"); 17014ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else { 170274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("Number of connected devices:" + deviceList.size()); 17034ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 17044ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectedDevices[0] = " + device); 17054ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("Priority of Connected device = " + mInputDevice.getPriority(device)); 17064ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 17074ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh switch (mInputDevice.getConnectionState(device)) { 17084ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTING: 17094ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTING"); 17104ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 17114ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTED: 17124ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTED"); 17134ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 17144ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_DISCONNECTING: 17154ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_DISCONNECTING"); 17164ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 17174ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 17184ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 17194ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh deviceList.clear(); 17204ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh deviceList = mInputDevice.getDevicesMatchingConnectionStates(new int[] { 17214ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 17224ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("--Connected and Disconnected input devices"); 17234ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 17244ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println(device); 17254ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 172624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 17274ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mAdapter.closeProfileProxy(BluetoothProfile.INPUT_DEVICE, mBluetoothHeadset); 17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 173074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private void dumpPanProfile(PrintWriter pw) { 173174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("\n--Bluetooth Service- Pan Profile"); 173274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (mPan != null) { 173374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh List<BluetoothDevice> deviceList = mPan.getConnectedDevices(); 173474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (deviceList.size() == 0) { 173574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No Pan devices connected"); 173674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else { 173774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("Number of connected devices:" + deviceList.size()); 173874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 173974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectedDevices[0] = " + device); 174074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("Priority of Connected device = " + mPan.getPriority(device)); 174174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 174274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh switch (mPan.getConnectionState(device)) { 174374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTING: 174474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTING"); 174574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 174674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTED: 174774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTED"); 174874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 174974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_DISCONNECTING: 175074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_DISCONNECTING"); 175174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 175274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 175374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 175474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh deviceList.clear(); 175574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh deviceList = mPan.getDevicesMatchingConnectionStates(new int[] { 175674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 175774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("--Connected and Disconnected Pan devices"); 175874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 175974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println(device); 176074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 176174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 17629a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 17649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpHeadsetConnectionState(PrintWriter pw, 17659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDevice device) { 17669a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby switch (mBluetoothHeadset.getConnectionState(device)) { 17679a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_CONNECTING: 17689a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_CONNECTING"); 17699a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 17709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_CONNECTED: 17719a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_CONNECTED"); 17729a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 17739a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_DISCONNECTING: 17749a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_DISCONNECTING"); 17759a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 17769a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_AUDIO_CONNECTED: 17779a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_AUDIO_CONNECTED"); 17789a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 17799a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17809a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17819a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 17829a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpApplicationServiceRecords(PrintWriter pw) { 17839a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--Application Service Records--"); 17849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (Integer handle : mServiceRecordToPid.keySet()) { 17859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Integer pid = mServiceRecordToPid.get(handle); 17869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle)); 17879a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 178874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mAdapter.closeProfileProxy(BluetoothProfile.PAN, mBluetoothHeadset); 178974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 179074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 17919a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpAclConnectedDevices(PrintWriter pw) { 17929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] devicesObjectPath = getKnownDevices(); 17939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--ACL connected devices--"); 17949a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (devicesObjectPath != null) { 17959a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String device : devicesObjectPath) { 17969a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println(getAddressFromObjectPath(device)); 17979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17989a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 18019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpKnownDevices(PrintWriter pw) { 18029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--Known devices--"); 18039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String address : mDeviceProperties.keySet()) { 18049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int bondState = mBondState.getBondState(address); 18059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.printf("%s %10s (%d) %s\n", address, 18069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby toBondStateString(bondState), 18079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mBondState.getAttempt(address), 18089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby getRemoteName(address)); 18099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 18109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Map<ParcelUuid, Integer> uuidChannels = mDeviceServiceChannelCache.get(address); 18119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (uuidChannels == null) { 18129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tuuids = null"); 18139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } else { 18149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (ParcelUuid uuid : uuidChannels.keySet()) { 18159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Integer channel = uuidChannels.get(uuid); 18169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (channel == null) { 18179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\t" + uuid); 18189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } else { 18199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\t" + uuid + " RFCOMM channel = " + channel); 18209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (RemoteService service : mUuidCallbackTracker.keySet()) { 18249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (service.address.equals(address)) { 18259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tPENDING CALLBACK: " + service.uuid); 18269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 18319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpBluetoothState(PrintWriter pw) { 18329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby switch(mBluetoothState) { 18339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothAdapter.STATE_OFF: 18349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("Bluetooth OFF\n"); 18359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 18369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothAdapter.STATE_TURNING_ON: 18379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("Bluetooth TURNING ON\n"); 18389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 18399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothAdapter.STATE_TURNING_OFF: 18409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("Bluetooth TURNING OFF\n"); 18419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 18429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothAdapter.STATE_ON: 18439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("Bluetooth ON\n"); 18449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 18459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby default: 18469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("Bluetooth UNKNOWN STATE " + mBluetoothState); 18479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 185096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 185196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh new BluetoothProfile.ServiceListener() { 185296a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh public void onServiceConnected(int profile, BluetoothProfile proxy) { 18534ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (profile == BluetoothProfile.HEADSET) { 18544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mBluetoothHeadset = (BluetoothHeadset) proxy; 18554ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else if (profile == BluetoothProfile.INPUT_DEVICE) { 18564ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mInputDevice = (BluetoothInputDevice) proxy; 185774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else if (profile == BluetoothProfile.PAN) { 185874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mPan = (BluetoothPan) proxy; 18594ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 18604ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 186196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh public void onServiceDisconnected(int profile) { 18624ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (profile == BluetoothProfile.HEADSET) { 18634ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mBluetoothHeadset = null; 18644ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else if (profile == BluetoothProfile.INPUT_DEVICE) { 18654ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mInputDevice = null; 186674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else if (profile == BluetoothProfile.PAN) { 186774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mPan = null; 18684ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 186996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 187096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh }; 187196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 1872d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) { 1873d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (pairable && discoverable) 1874bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1875d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else if (pairable && !discoverable) 1876bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 1877d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 1878bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static String scanModeToBluezString(int mode) { 18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mode) { 1883bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "off"; 1885bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "connectable"; 1887bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "discoverable"; 18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1893d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getAddressFromObjectPath(String objectPath) { 18949a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String adapterObjectPath = mAdapterProperties.getObjectPath(); 1895d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (adapterObjectPath == null || objectPath == null) { 1896f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath + 1897d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " or deviceObjectPath:" + objectPath + " is null"); 1898d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1899d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1900d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!objectPath.startsWith(adapterObjectPath)) { 1901f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath + 1902d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " is not a prefix of deviceObjectPath:" + objectPath + 1903d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh "bluetoothd crashed ?"); 1904d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1905d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1906d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String address = objectPath.substring(adapterObjectPath.length()); 1907d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (address != null) return address.replace('_', ':'); 1908d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1909d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: Address being returned is null"); 1910d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1911d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1912d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1913d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getObjectPathFromAddress(String address) { 19149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String path = mAdapterProperties.getObjectPath(); 1915d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (path == null) { 1916d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "Error: Object Path is null"); 1917d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1918d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1919d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh path = path + address.replace(":", "_"); 1920d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return path; 1921d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1922d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1923b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh /*package */ void setLinkTimeout(String address, int num_slots) { 1924b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh String path = getObjectPathFromAddress(address); 1925b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh boolean result = setLinkTimeoutNative(path, num_slots); 1926b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 19279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (!result) Log.d(TAG, "Set Link Timeout to " + num_slots + " slots failed"); 1928b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh } 1929b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 193030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /**** Handlers for PAN Profile ****/ 193130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 193230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized boolean isTetheringOn() { 193330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 193430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothPanProfileHandler.isTetheringOn(); 193530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 193630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 193730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /*package*/ synchronized boolean allowIncomingTethering() { 193830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothPanProfileHandler.allowIncomingTethering(); 193930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 194030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 194130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized void setBluetoothTethering(boolean value) { 194230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 194330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mBluetoothPanProfileHandler.setBluetoothTethering(value); 194430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 194530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 194674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh public synchronized int getPanDeviceConnectionState(BluetoothDevice device) { 194730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 194874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return mBluetoothPanProfileHandler.getPanDeviceConnectionState(device); 194930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 195030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 195130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized boolean connectPanDevice(BluetoothDevice device) { 195230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 195330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 195430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothPanProfileHandler.connectPanDevice(device); 195530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 195630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 195730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized List<BluetoothDevice> getConnectedPanDevices() { 195830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 195930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothPanProfileHandler.getConnectedPanDevices(); 196030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 196130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 196274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh public synchronized List<BluetoothDevice> getPanDevicesMatchingConnectionStates( 196374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh int[] states) { 196474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 196574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return mBluetoothPanProfileHandler.getPanDevicesMatchingConnectionStates(states); 196674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 196774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 196830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized boolean disconnectPanDevice(BluetoothDevice device) { 196930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 197030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 197130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothPanProfileHandler.disconnectPanDevice(device); 197230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 197330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 197430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device, 197530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh String iface, 197630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int state, 197730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int role) { 197830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, iface, state, role); 197930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 198030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 198130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device, 198230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int state, int role) { 198330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, null, state, role); 198430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 198530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 198630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /**** Handlers for Input Device Profile ****/ 198730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 198830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized boolean connectInputDevice(BluetoothDevice device) { 198930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 199030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 199130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress()); 199230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothInputProfileHandler.connectInputDevice(device, state); 199330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 199430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 199530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized boolean connectInputDeviceInternal(BluetoothDevice device) { 199630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothInputProfileHandler.connectInputDeviceInternal(device); 199730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 199830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 199930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized boolean disconnectInputDevice(BluetoothDevice device) { 200030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 200130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 200230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress()); 200330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothInputProfileHandler.disconnectInputDevice(device, state); 200430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 200530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 200630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized boolean disconnectInputDeviceInternal(BluetoothDevice device) { 200730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device); 200830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 200930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20104ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh public synchronized int getInputDeviceConnectionState(BluetoothDevice device) { 201130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 20124ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device); 201330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 201430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 201530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 201630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized List<BluetoothDevice> getConnectedInputDevices() { 201730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 201830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothInputProfileHandler.getConnectedInputDevices(); 201930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 202030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20214ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh public synchronized List<BluetoothDevice> getInputDevicesMatchingConnectionStates( 20224ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh int[] states) { 20234ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 20244ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states); 20254ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 20264ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 20274ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 202830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized int getInputDevicePriority(BluetoothDevice device) { 202930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 203030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothInputProfileHandler.getInputDevicePriority(device); 203130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 203230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 203330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh public synchronized boolean setInputDevicePriority(BluetoothDevice device, int priority) { 203430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 203530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 203630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothInputProfileHandler.setInputDevicePriority(device, priority); 203730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 203830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 203930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /*package*/synchronized List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) { 204030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh return mBluetoothInputProfileHandler.lookupInputDevicesMatchingStates(states); 204130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 204230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 204330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /*package*/ synchronized void handleInputDevicePropertyChange(String address, boolean connected) { 204430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mBluetoothInputProfileHandler.handleInputDevicePropertyChange(address, connected); 204530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 204630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20479b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectHeadset(String address) { 204896a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 204996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2050f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 20519b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2052f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2053f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING; 2054f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2055f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.sendMessage(msg); 2056f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh return true; 20579b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20589b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 20599b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20609b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 20619b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectHeadset(String address) { 206296a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 206396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2064f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 20659b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2066f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2067f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HFP_OUTGOING; 2068f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2069f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.sendMessage(msg); 20709b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 20719b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20729b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 20739b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20749b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 20759b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectSink(String address) { 207696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 207796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2078f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 20799b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2080f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2081f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING; 2082f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2083f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.sendMessage(msg); 2084f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh return true; 20859b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20869b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 20879b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 20889b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 20899b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectSink(String address) { 209096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 209196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2092f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 20939b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2094f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2095f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_A2DP_OUTGOING; 2096f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2097f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.sendMessage(msg); 20989b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 20999b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21009b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 21019b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21029b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDeviceProfileState addProfileState(String address) { 2104f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 21059b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) return state; 21069b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 2107f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh state = new BluetoothDeviceProfileState(mContext, address, this, mA2dpService); 2108f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.put(address, state); 21099b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.start(); 21109b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return state; 21119b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21129b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void removeProfileState(String address) { 2114f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.remove(address); 21159b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21169b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby synchronized String[] getKnownDevices() { 21189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = null; 21199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = getProperty("Devices"); 21209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (val != null) { 21219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby bonds = val.split(","); 21229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 21239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return bonds; 21249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 21259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 21269b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private void initProfileState() { 21279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = null; 21289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = mAdapterProperties.getProperty("Devices"); 21299b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (val != null) { 21309b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh bonds = val.split(","); 21319b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21329b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (bonds == null) { 21339b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return; 21349b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21359b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh for (String path : bonds) { 21369b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh String address = getAddressFromObjectPath(path); 2137f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = addProfileState(address); 21389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 21399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 21409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 21419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void autoConnect() { 21429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = getKnownDevices(); 21439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (bonds == null) { 21449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return; 21459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 21469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String path : bonds) { 21479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String address = getAddressFromObjectPath(path); 21489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 21499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (state != null) { 21509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Message msg = new Message(); 21519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby msg.what = BluetoothDeviceProfileState.AUTO_CONNECT_PROFILES; 21529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state.sendMessage(msg); 21539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 21549b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21559b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21569b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21579b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean notifyIncomingConnection(String address) { 2158f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = 2159f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.get(address); 21609b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 21619b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 2162f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.what = BluetoothDeviceProfileState.CONNECT_HFP_INCOMING; 21639b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(msg); 21649b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 21659b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21669b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 21679b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21689b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21699b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /*package*/ boolean notifyIncomingA2dpConnection(String address) { 2170f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = 2171f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.get(address); 21729b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 21739b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 2174f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.what = BluetoothDeviceProfileState.CONNECT_A2DP_INCOMING; 21759b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(msg); 21769b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 21779b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21789b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 21799b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21809b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21819b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /*package*/ void setA2dpService(BluetoothA2dpService a2dpService) { 21829b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh mA2dpService = a2dpService; 21839b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21849b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 218570a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh public void sendProfileStateMessage(int profile, int cmd) { 218670a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh Message msg = new Message(); 218770a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh msg.what = cmd; 218870a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh if (profile == BluetoothProfileState.HFP) { 218970a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh mHfpProfileState.sendMessage(msg); 219070a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } else if (profile == BluetoothProfileState.A2DP) { 219170a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh mA2dpProfileState.sendMessage(msg); 219270a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } 219370a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } 219470a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh 2195c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh public int getAdapterConnectionState() { 2196c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh return mAdapterConnectionState; 2197c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh } 2198c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 2199a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh public synchronized void sendConnectionStateChange(BluetoothDevice device, int state, 2200a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh int prevState) { 22019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Since this is a binder call check if Bluetooth is on still 22029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (mBluetoothState == BluetoothAdapter.STATE_OFF) return; 22039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 22049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (updateCountersAndCheckForConnectionStateChange(state, prevState)) { 22059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (!validateProfileConnectionState(state) || 22069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby !validateProfileConnectionState(prevState)) { 22079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Previously, an invalid state was broadcast anyway, 22089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // with the invalid state converted to -1 in the intent. 22099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Better to log an error and not send an intent with 22109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // invalid contents or set mAdapterConnectionState to -1. 22119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "Error in sendConnectionStateChange: " 22129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + "prevState " + prevState + " state " + state); 22139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return; 22149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 2215c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 2216c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh mAdapterConnectionState = state; 2217c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 2218a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 2219a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 22209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 22219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby convertToAdapterState(state)); 22229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, 22239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby convertToAdapterState(prevState)); 2224a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 22259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "CONNECTION_STATE_CHANGE: " + device + ": " 22269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + prevState + " -> " + state); 2227a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2228a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2229a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 22309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private boolean validateProfileConnectionState(int state) { 22319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (state == BluetoothProfile.STATE_DISCONNECTED || 22329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_CONNECTING || 22339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_CONNECTED || 22349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_DISCONNECTING); 22359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 22369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 22379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private int convertToAdapterState(int state) { 2238a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh switch (state) { 22399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_DISCONNECTED: 22409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_DISCONNECTED; 22419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_DISCONNECTING: 22429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_DISCONNECTING; 22439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_CONNECTED: 22449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_CONNECTED; 2245a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTING: 2246a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh return BluetoothAdapter.STATE_CONNECTING; 22479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 22489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "Error in convertToAdapterState"); 22499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return -1; 22509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 22519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 22529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) { 22539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby switch (prevState) { 22549a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_CONNECTING: 22559a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesConnecting--; 22569a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 22579a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 2258a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTED: 22599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesConnected--; 22609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 22619a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 2262a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTING: 22639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesDisconnecting--; 22649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 2265a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2266a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2267a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh switch (state) { 2268a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTING: 2269a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnecting++; 22709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesConnecting == 1); 2271a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2272a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTED: 2273a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnected++; 22749a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 1); 2275a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2276a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTING: 2277a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesDisconnecting++; 22789a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesDisconnecting == 1); 2279a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2280a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTED: 22819a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesConnecting == 0); 2282a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 22839a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby default: 22849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return true; 2285a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 22869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2287d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2288d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native static void classInitNative(); 2289d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void initializeNativeDataNative(); 2290d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setupNativeDataNative(); 2291d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean tearDownNativeDataNative(); 2292d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void cleanupNativeDataNative(); 22939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ native String getAdapterPathNative(); 2294d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2295d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int isEnabledNative(); 2296d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int enableNative(); 2297d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int disableNative(); 2298d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 22999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ native Object[] getAdapterPropertiesNative(); 2300d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native Object[] getDevicePropertiesNative(String objectPath); 2301d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyStringNative(String key, String value); 2302d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyIntegerNative(String key, int value); 2303d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyBooleanNative(String key, int value); 2304d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2305d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean startDiscoveryNative(); 2306d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean stopDiscoveryNative(); 2307d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2308d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean createPairedDeviceNative(String address, int timeout_ms); 2309cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native boolean createPairedDeviceOutOfBandNative(String address, int timeout_ms); 2310cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native byte[] readAdapterOutOfBandDataNative(); 2311cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 2312d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean cancelDeviceCreationNative(String address); 2313d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean removeDeviceNative(String objectPath); 2314d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int getDeviceServiceChannelNative(String objectPath, String uuid, 2315d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh int attributeId); 2316d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2317b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean cancelPairingUserInputNative(String address, int nativeData); 2318d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setPinNative(String address, String pin, int nativeData); 2319b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPasskeyNative(String address, int passkey, int nativeData); 2320b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPairingConfirmationNative(String address, boolean confirm, 2321b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh int nativeData); 2322cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native boolean setRemoteOutOfBandDataNative(String address, byte[] hash, 2323cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer, int nativeData); 2324cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 232524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean setDevicePropertyBooleanNative(String objectPath, String key, 232624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int value); 23271caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private native boolean createDeviceNative(String address); 232816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ native boolean discoverServicesNative(String objectPath, String pattern); 232910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 233024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb, 233124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly short channel); 233224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean removeServiceRecordNative(int handle); 2333b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh private native boolean setLinkTimeoutNative(String path, int num_slots); 233430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh native boolean connectInputDeviceNative(String path); 233530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh native boolean disconnectInputDeviceNative(String path); 23366fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 2337a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge); 2338a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean connectPanDeviceNative(String path, String dstRole); 2339a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean disconnectPanDeviceNative(String path); 2340a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean disconnectPanServerDeviceNative(String path, 2341a44a1e77ef435942b2ff60e9e60d3a64b43d775bJaikumar Ganesh String address, String iface); 234284690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh 234384690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private native int[] addReservedServiceRecordsNative(int[] uuuids); 234484690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private native boolean removeReservedServiceRecordsNative(int[] handles); 23459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2346