BluetoothService.java revision 7f9ecca8f2dc288f785b37d2478e89b80fc3cefc
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TODO: Move this to 19bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * java/services/com/android/server/BluetoothService.java 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and make the contructor package private again. 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.server; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.BluetoothAdapter; 28dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganeshimport android.bluetooth.BluetoothClass; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothDevice; 30f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganeshimport android.bluetooth.BluetoothDeviceProfileState; 315a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport android.bluetooth.BluetoothHeadset; 322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.bluetooth.BluetoothHealthAppConfiguration; 334ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganeshimport android.bluetooth.BluetoothInputDevice; 346fdd0c6274c81b337ad35b70480f881daf7354c3Danica Changimport android.bluetooth.BluetoothPan; 3596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganeshimport android.bluetooth.BluetoothProfile; 36f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganeshimport android.bluetooth.BluetoothProfileState; 3724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pellyimport android.bluetooth.BluetoothSocket; 3810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganeshimport android.bluetooth.BluetoothUuid; 39bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.IBluetooth; 4016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport android.bluetooth.IBluetoothCallback; 41fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganeshimport android.bluetooth.IBluetoothHealthCallback; 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; 522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.os.ParcelFileDescriptor; 533fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.ParcelUuid; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 55105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.os.ServiceManager; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 58cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganeshimport android.util.Pair; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 60fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganeshimport com.android.internal.app.IBatteryStats; 61fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh 623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedInputStream; 63a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.BufferedReader; 643fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedWriter; 65a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.DataInputStream; 66a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.File; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 683fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileInputStream; 693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileNotFoundException; 703fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileWriter; 71a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.InputStreamReader; 723fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.IOException; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 74a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.RandomAccessFile; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.UnsupportedEncodingException; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 7916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport java.util.Iterator; 805a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 83bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellypublic class BluetoothService extends IBluetooth.Stub { 84bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private static final String TAG = "BluetoothService"; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean DBG = true; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNativeData; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BluetoothEventLoop mEventLoop; 8996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh private BluetoothHeadset mBluetoothHeadset; 904ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh private BluetoothInputDevice mInputDevice; 9174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private BluetoothPan mPan; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsAirplaneSensitive; 9344303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey private boolean mIsAirplaneToggleable; 947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private BluetoothAdapterStateMachine mBluetoothState; 95997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly private boolean mRestart = false; // need to call enable() after disable() 96bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private boolean mIsDiscovering; 9784690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private int[] mAdapterSdpHandles; 9850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private ParcelUuid[] mAdapterUuids; 99997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 100bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private BluetoothAdapter mAdapter; // constant after init() 1019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothBondState mBondState; // local cache of bondings 102105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private final IBatteryStats mBatteryStats; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 106a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1083fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_ADDRESS_PATH = "/sys/class/switch/dock/bt_addr"; 1093fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_PIN_PATH = "/sys/class/switch/dock/bt_pin"; 1103fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1116e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address"; 1126e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings"; 1136e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 1147f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private static final int MESSAGE_UUID_INTENT = 1; 1157f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 2; 116a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 117a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // The time (in millisecs) to delay the pairing attempt after the first 118a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // auto pairing attempt fails. We use an exponential delay with 119a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and 120a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value. 121a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000; 122a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000; 1231caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 1241caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // The timeout used to sent the UUIDs Intent 1251caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // This timeout should be greater than the page timeout 1261caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private static final int UUID_INTENT_DELAY = 6000; 127105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 12816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** Always retrieve RFCOMM channel for these SDP UUIDs */ 12916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static final ParcelUuid[] RFCOMM_UUIDS = { 13016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.Handsfree, 13116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.HSP, 13216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.ObexObjectPush }; 13316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothAdapterProperties mAdapterProperties; 1359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothDeviceProperties mDeviceProperties; 136d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 13716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache; 13816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final ArrayList<String> mUuidIntentTracker; 13916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker; 1401caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 14124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private final HashMap<Integer, Integer> mServiceRecordToPid; 14224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 143f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState; 144f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final BluetoothProfileState mA2dpProfileState; 145f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final BluetoothProfileState mHfpProfileState; 1469b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 1479b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private BluetoothA2dpService mA2dpService; 148cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData; 149545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 150a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh private int mProfilesConnected = 0, mProfilesConnecting = 0, mProfilesDisconnecting = 0; 151707952ecd4b6cae25aabcf51f94d702a65847e9eJaikumar Ganesh 1523fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static String mDockAddress; 1533fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private String mDockPin; 1543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 155c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED; 156a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh private BluetoothPanProfileHandler mBluetoothPanProfileHandler; 15730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh private BluetoothInputProfileHandler mBluetoothInputProfileHandler; 1582ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private BluetoothHealthProfileHandler mBluetoothHealthProfileHandler; 159a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private static final String INCOMING_CONNECTION_FILE = 160a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie "/data/misc/bluetooth/incoming_connection.conf"; 161a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private HashMap<String, Pair<Integer, String>> mIncomingConnections; 162c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 16316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static class RemoteService { 16416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public String address; 16516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public ParcelUuid uuid; 16616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public RemoteService(String address, ParcelUuid uuid) { 16716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.address = address; 16816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.uuid = uuid; 16916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 17016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly @Override 17116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public boolean equals(Object o) { 17216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (o instanceof RemoteService) { 17316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = (RemoteService)o; 17416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return address.equals(service.address) && uuid.equals(service.uuid); 17516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 17616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 17716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 1785f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root 1795f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root @Override 1805f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root public int hashCode() { 1815f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root int hash = 1; 1825f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (address == null ? 0 : address.hashCode()); 1835f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (uuid == null ? 0 : uuid.hashCode()); 1845f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root return hash; 1855f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root } 18616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 18716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project classInitNative(); 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 192bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public BluetoothService(Context context) { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 194105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 195105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Need to do this in place of: 196105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // mBatteryStats = BatteryStatsService.getService(); 197105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Since we can not import BatteryStatsService from here. This class really needs to be 198105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // moved to java/services/com/android/server/ 199105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initializeNativeDataNative(); 202ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 203ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (isEnabledNative() == 1) { 204ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Log.w(TAG, "Bluetooth daemons already running - runtime restart? "); 205ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project disableNative(); 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 207ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsDiscovering = false; 209a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh 2109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mBondState = new BluetoothBondState(context, this); 2119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mAdapterProperties = new BluetoothAdapterProperties(context, this); 2129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties = new BluetoothDeviceProperties(this); 21310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 21410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>(); 215cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mDeviceOobData = new HashMap<String, Pair<byte[], byte[]>>(); 2161caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker = new ArrayList<String>(); 21716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>(); 21824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid = new HashMap<Integer, Integer>(); 219f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>(); 220f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP); 221f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP); 222f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh 223f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.start(); 224f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.start(); 2253fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2263fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh IntentFilter filter = new IntentFilter(); 2276e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh registerForAirplaneMode(filter); 2286e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 2293fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh filter.addAction(Intent.ACTION_DOCK_EVENT); 2306e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.registerReceiver(mReceiver, filter); 23130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this); 232a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this); 2332ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this); 234a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mIncomingConnections = new HashMap<String, Pair<Integer, String>>(); 2353fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2363fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2379b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public static synchronized String readDockBluetoothAddress() { 2383fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (mDockAddress != null) return mDockAddress; 2393fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2403fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedInputStream file = null; 2413fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh String dockAddress; 2423fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2433fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file = new BufferedInputStream(new FileInputStream(DOCK_ADDRESS_PATH)); 2443fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh byte[] address = new byte[17]; 2453fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.read(address); 2463fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = new String(address); 2473fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = dockAddress.toUpperCase(); 2483fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (BluetoothAdapter.checkBluetoothAddress(dockAddress)) { 2493fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = dockAddress; 2503fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockAddress; 2513fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } else { 2529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "CheckBluetoothAddress failed for car dock address: " 2539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + dockAddress); 2543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2553fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2569a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "FileNotFoundException while trying to read dock address"); 2573fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "IOException while trying to read dock address"); 2593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 2603fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (file != null) { 2613fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.close(); 2633fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2643fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 2653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2663fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2673fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2683fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = null; 2693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return null; 2703fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2713fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2723fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private synchronized boolean writeDockPin() { 2733fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedWriter out = null; 2743fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2753fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out = new BufferedWriter(new FileWriter(DOCK_PIN_PATH)); 2763fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2773fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Generate a random 4 digit pin between 0000 and 9999 2783fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // This is not truly random but good enough for our purposes. 2793fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh int pin = (int) Math.floor(Math.random() * 10000); 2803fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2813fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = String.format("%04d", pin); 2823fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.write(mDockPin); 2833fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return true; 2843fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "FileNotFoundException while trying to write dock pairing pin"); 2863fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2879a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "IOException while while trying to write dock pairing pin"); 2883fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 2893fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (out != null) { 2903fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2913fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.close(); 2923fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2933fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 2943fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2953fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2963fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2973fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = null; 2983fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 2993fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 3003fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 3013fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh /*package*/ synchronized String getDockPin() { 3023fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockPin; 303bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly } 304bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly 305bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public synchronized void initAfterRegistration() { 306f242b7b931898856bcbcb7ec36cacf43098ba544Nick Pelly mAdapter = BluetoothAdapter.getDefaultAdapter(); 3077f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter); 3087f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.start(); 3097f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mEventLoop = mBluetoothState.getBluetoothEventLoop(); 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3127d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh public synchronized void initAfterA2dpRegistration() { 3137d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh mEventLoop.getProfileProxy(); 3147d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh } 3157d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 3186e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.unregisterReceiver(mReceiver); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cleanupNativeDataNative(); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isEnabled() { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 3288c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh return isEnabledInternal(); 3298c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh } 3308c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 3318c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh private boolean isEnabledInternal() { 3327f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return (getBluetoothStateInternal() == BluetoothAdapter.STATE_ON); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 335105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public int getBluetoothState() { 336105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 3377f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return getBluetoothStateInternal(); 338105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 339105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int getBluetoothStateInternal() { 3417f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return mBluetoothState.getBluetoothAdapterState(); 3429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 343105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth and disable BT in settings. Returns true on success. 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean disable() { 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return disable(true); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth. Returns true on success. 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 354e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly * @param saveSetting If true, persist the new setting 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean disable(boolean saveSetting) { 357e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3597f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie int adapterState = getBluetoothStateInternal(); 3607f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 3617f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie switch (adapterState) { 362de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_OFF: 363105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 364de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_ON: 365105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 366105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project default: 367105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return false; 368105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 3697a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh 3707f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_OFF, saveSetting); 371105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 372105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 373105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie synchronized void disconnectDevices() { 3757a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh // Disconnect devices handled by BluetoothService. 3767a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh for (BluetoothDevice device: getConnectedInputDevices()) { 3777a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh disconnectInputDevice(device); 3787a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 3797a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh 3807a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh for (BluetoothDevice device: getConnectedPanDevices()) { 3817a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh disconnectPanDevice(device); 3827a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 3837a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 384105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 3867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * The Bluetooth has been turned off, but hot. Do bonding, profile, 3877f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * and internal cleanup 3887f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 3897f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie synchronized void finishDisable() { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mark in progress bondings as cancelled 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) { 392005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3962d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh // Stop the profile state machine for bonded devices. 3972d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDED)) { 3982d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh removeProfileState(address); 3992d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh } 4002d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // update mode 402de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 403de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 406105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mIsDiscovering = false; 407bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.clear(); 40824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.clear(); 409105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 410a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnected = 0; 411a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnecting = 0; 412a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesDisconnecting = 0; 413c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED; 41450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids = null; 41550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterSdpHandles = null; 416a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 417105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Log bluetooth off to battery stats. 418105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project long ident = Binder.clearCallingIdentity(); 419105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project try { 420105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats.noteBluetoothOff(); 421105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } catch (RemoteException e) { 422105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } finally { 423105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Binder.restoreCallingIdentity(ident); 424105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 425997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 426997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (mRestart) { 427997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 428997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly enable(); 429997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4327f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 4337f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * power off Bluetooth 4347f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 4357f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie synchronized void shutoffBluetooth() { 4367f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie tearDownNativeDataNative(); 4377f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie disableNative(); 4387f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (mRestart) { 4397f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mRestart = false; 4407f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie enable(); 4417f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4427f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4437f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 444105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /** Bring up BT and persist BT on in settings */ 445105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public boolean enable() { 446105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return enable(true); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enable this Bluetooth device, asynchronously. 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This turns on/off the underlying hardware. 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 453105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @param saveSetting If true, persist the new state of BT in settings 454105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @return True on success (so far) 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 456105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public synchronized boolean enable(boolean saveSetting) { 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Airplane mode can prevent Bluetooth radio from being turned on. 46144303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4647f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting); 4657f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return true; 4667f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4677f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 4687f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 4697f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Turn on Bluetooth Module, Load firmware, and do all the preparation 4707f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * needed to get the Bluetooth Module ready but keep it not discoverable 4717f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * and not connectable. 4727f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 4737f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /* package */ synchronized boolean prepareBluetooth() { 4747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (!setupNativeDataNative()) { 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mIsDiscovering = false; 4787f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 4797f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie switchConnectable(false); 4807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie updateSdpRecords(); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 484997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /** Forcibly restart Bluetooth if it is on */ 485997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /* package */ synchronized void restart() { 4867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) { 487997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly return; 488997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 489997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = true; 490997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (!disable(false)) { 491997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 492997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 493d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 494997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Handler mHandler = new Handler() { 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 4991caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh case MESSAGE_UUID_INTENT: 5001caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String address = (String)msg.obj; 50116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (address != null) { 5021caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh sendUuidIntent(address); 50316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly makeServiceChannelCallbacks(address); 50416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 5051caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh break; 506a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY: 507a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh address = (String)msg.obj; 508a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (address != null) { 509a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh createBond(address); 510a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 511a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 512a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh break; 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 51750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) { 51850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh //Register SDP records. 51950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh int[] svcIdentifiers = new int[uuids.size()]; 52050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh for (int i = 0; i < uuids.size(); i++) { 52150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh svcIdentifiers[i] = BluetoothUuid.getServiceIdentifierFromParcelUuid(uuids.get(i)); 52250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 52350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterSdpHandles = addReservedServiceRecordsNative(svcIdentifiers); 52450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 525105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 52650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private synchronized void updateSdpRecords() { 52750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh ArrayList<ParcelUuid> uuids = new ArrayList<ParcelUuid>(); 52850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 52950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add the default records 53050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.HSP_AG); 53150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.ObexObjectPush); 53250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 53350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh if (mContext.getResources(). 53450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh getBoolean(com.android.internal.R.bool.config_voice_capable)) { 53550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.Handsfree_AG); 53650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.PBAP_PSE); 53750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 53850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 53950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add SDP records for profiles maintained by Android userspace 54050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh addReservedSdpRecords(uuids); 54150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 54250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Enable profiles maintained by Bluez userspace. 54374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE, 54474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothPanProfileHandler.NAP_BRIDGE); 54550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 54650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add SDP records for profiles maintained by Bluez userspace 54750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.AudioSource); 54850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.AvrcpTarget); 54950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.NAP); 55050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 55150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Cannot cast uuids.toArray directly since ParcelUuid is parcelable 55250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids = new ParcelUuid[uuids.size()]; 55350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh for (int i = 0; i < uuids.size(); i++) { 55450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids[i] = uuids.get(i); 55550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 55650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 55750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 5589efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh /** 5599efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * This function is called from Bluetooth Event Loop when onPropertyChanged 5609efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * for adapter comes in with UUID property. 5619efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * @param uuidsThe uuids of adapter as reported by Bluez. 5629efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh */ 5637f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ synchronized void updateBluetoothState(String uuids) { 5647f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids); 5659efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh 5667f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (mAdapterUuids != null && 5677f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) { 5687f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5727f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 5737f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * This method is called immediately after Bluetooth module is turned on. 5747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * It starts auto-connection and places bluetooth on sign onto the battery 5757f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * stats 5767f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 5777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ void runBluetooth() { 5787f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mIsDiscovering = false; 5797f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBondState.readAutoPairingData(); 5807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBondState.initBondState(); 5817f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie initProfileState(); 5827f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 5837f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie autoConnect(); 5847f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 5857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // Log bluetooth on to battery stats. 5867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie long ident = Binder.clearCallingIdentity(); 5877f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie try { 5887f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBatteryStats.noteBluetoothOn(); 5897f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } catch (RemoteException e) { 5907f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Log.e(TAG, "", e); 5917f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } finally { 5927f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Binder.restoreCallingIdentity(ident); 5937f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 596a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean attemptAutoPair(String address) { 597a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (!mBondState.hasAutoPairingFailed(address) && 598a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh !mBondState.isAutoPairingBlacklisted(address)) { 599a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.attempt(address); 600a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setPin(address, BluetoothDevice.convertPinToBytes("0000")); 601a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return true; 602a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 603a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return false; 604a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 605a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 606f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh /*package*/ synchronized boolean isFixedPinZerosAutoPairKeyboard(String address) { 607f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh // Check for keyboards which have fixed PIN 0000 as the pairing pin 608f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh return mBondState.isFixedPinZerosAutoPairKeyboard(address); 609f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh } 610f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh 611a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized void onCreatePairedDeviceResult(String address, int result) { 612a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (result == BluetoothDevice.BOND_SUCCESS) { 613a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_BONDED); 614a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (mBondState.isAutoPairingAttemptsInProgress(address)) { 615a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 616a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 617a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED && 618a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.getAttempt(address) == 1) { 619a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.addAutoPairingFailure(address); 620a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh pairingAttempt(address, result); 621a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN && 622a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.isAutoPairingAttemptsInProgress(address)) { 623a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh pairingAttempt(address, result); 624a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else { 625a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_NONE, result); 626a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (mBondState.isAutoPairingAttemptsInProgress(address)) { 627a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 628a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 629a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 630a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 631a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 632a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized String getPendingOutgoingBonding() { 633a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return mBondState.getPendingOutgoingBonding(); 634a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 635a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 636a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private void pairingAttempt(String address, int result) { 637a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // This happens when our initial guess of "0000" as the pass key 638a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // fails. Try to create the bond again and display the pin dialog 639a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // to the user. Use back-off while posting the delayed 640a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // message. The initial value is 641a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is 642a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is 643a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // reached, display an error to the user. 644a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh int attempt = mBondState.getAttempt(address); 645a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY > 646a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) { 647a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 648a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_NONE, result); 649a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 650a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 651a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 652a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh Message message = mHandler.obtainMessage(MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); 653a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh message.obj = address; 654a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh boolean postResult = mHandler.sendMessageDelayed(message, 655a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); 656a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (!postResult) { 657a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 658a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, 659a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh BluetoothDevice.BOND_NONE, result); 660a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 661a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 662a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.attempt(address); 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ BluetoothDevice getRemoteDevice(String address) { 6669a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapter.getRemoteDevice(address); 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String toBondStateString(int bondState) { 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (bondState) { 671005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly case BluetoothDevice.BOND_NONE: 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "not bonded"; 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDING: 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonding"; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDED: 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonded"; 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "??????"; 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setName(String name) { 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == null) { 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 688d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyString("Name", name); 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 691d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh //TODO(): setPropertyString, setPropertyInteger, setPropertyBoolean 692d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Either have a single property function with Object as the parameter 693d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // or have a function for each property and then obfuscate in the JNI layer. 694d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The following looks dirty. 695d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyString(String key, String value) { 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 6978c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 698d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyStringNative(key, value); 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 701d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyInteger(String key, int value) { 702d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 7038c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 704d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyIntegerNative(key, value); 705d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 707d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyBoolean(String key, boolean value) { 708d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 7098c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 710d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyBooleanNative(key, value ? 1 : 0); 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 713d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /** 714d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Set the discoverability window for the device. A timeout of zero 715d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * makes the device permanently discoverable (if the device is 716d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * discoverable). Setting the timeout to a nonzero value does not make 717d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * a device discoverable; you need to call setMode() to make the device 718d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * explicitly discoverable. 719d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 720f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby * @param timeout The discoverable timeout in seconds. 721d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh */ 722d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean setDiscoverableTimeout(int timeout) { 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 725d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyInteger("DiscoverableTimeout", timeout); 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 72812835478ee687a493d1b5882e67b6725bd539c26Nick Pelly public synchronized boolean setScanMode(int mode, int duration) { 72918b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, 73018b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly "Need WRITE_SECURE_SETTINGS permission"); 7317f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return setScanMode(mode, duration, true); 7327f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7337f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 7347f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 7357f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * @param on true set the local Bluetooth module to be connectable 7367f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * but not dicoverable 7377f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * false set the local Bluetooth module to be not connectable 7387f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * and not dicoverable 7397f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 7407f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ synchronized void switchConnectable(boolean on) { 7417f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (on) { 7427f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // 0 is a dummy value, does not apply for SCAN_MODE_CONNECTABLE 7437f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, 0, false); 7447f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else { 7457f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // 0 is a dummy value, does not apply for SCAN_MODE_NONE 7467f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setScanMode(BluetoothAdapter.SCAN_MODE_NONE, 0, false); 7477f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7487f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7497f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 7507f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private synchronized boolean setScanMode(int mode, int duration, boolean allowOnlyInOnState) { 7519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean pairable; 7529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean discoverable; 75312835478ee687a493d1b5882e67b6725bd539c26Nick Pelly 754de893f550301a60274e87aa8168225e7a7a42184Nick Pelly switch (mode) { 755de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 756d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = false; 757d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 758de893f550301a60274e87aa8168225e7a7a42184Nick Pelly break; 759de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 760d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 761d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 762005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 763de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 764d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 765d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = true; 76612835478ee687a493d1b5882e67b6725bd539c26Nick Pelly if (DBG) Log.d(TAG, "BT Discoverable for " + duration + " seconds"); 767005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 768de893f550301a60274e87aa8168225e7a7a42184Nick Pelly default: 769de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Log.w(TAG, "Requested invalid scan mode " + mode); 770de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return false; 771d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7737f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (allowOnlyInOnState) { 7747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setPropertyBoolean("Pairable", pairable); 7757f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setPropertyBoolean("Discoverable", discoverable); 7767f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else { 7777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // allowed to set the property through native layer directly 7787f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setAdapterPropertyBooleanNative("Pairable", pairable ? 1 : 0); 7797f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setAdapterPropertyBooleanNative("Discoverable", discoverable ? 1 : 0); 7807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 781d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return true; 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 784b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh /*package*/ synchronized String getProperty(String name) { 785b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh if (!isEnabledInternal()) return null; 7869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapterProperties.getProperty(name); 787b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh } 788b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh 7899a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothAdapterProperties getAdapterProperties() { 7909a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapterProperties; 7919a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 7929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 7939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDeviceProperties getDeviceProperties() { 7949a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties; 7959a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 7969a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 7979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean isRemoteDeviceInCache(String address) { 7989a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties.isInCache(address); 7999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void setRemoteDeviceProperty(String address, String name, String value) { 8029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties.setProperty(address, name, value); 8039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void updateRemoteDevicePropertiesCache(String address) { 8069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties.updateCache(address); 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getAddress() { 810d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 811d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Address"); 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 814d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getName() { 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 816d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Name"); 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 81958b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh public synchronized ParcelUuid[] getUuids() { 82058b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 82158b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh String value = getProperty("UUIDs"); 82258b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh if (value == null) return null; 82350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh return convertStringToParcelUuid(value); 82450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 82558b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 82650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private synchronized ParcelUuid[] convertStringToParcelUuid(String value) { 82758b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh String[] uuidStrings = null; 82858b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh // The UUIDs are stored as a "," separated string. 82958b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh uuidStrings = value.split(","); 83058b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; 83158b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 83258b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh for (int i = 0; i < uuidStrings.length; i++) { 83358b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh uuids[i] = ParcelUuid.fromString(uuidStrings[i]); 83458b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh } 83558b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh return uuids; 83658b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh } 83758b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 83858b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 840d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Returns the user-friendly name of a remote device. This value is 841d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * returned from our local cache, which is updated when onPropertyChange 842d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * event is received. 843d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Do not expect to retrieve the updated remote name immediately after 844d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * changing the name on the remote device. 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 846d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Bluetooth address of remote device. 847d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 848d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return The user-friendly name of the specified remote device. 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 850d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getRemoteName(String address) { 851d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 852005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 853d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 854d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 8559a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties.getProperty(address, "Name"); 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the discoverability window for the device. A timeout of zero 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * means that the device is permanently discoverable (if the device is 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the discoverable mode). 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The discoverability window of the device, in seconds. A negative 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value indicates an error. 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getDiscoverableTimeout() { 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 868d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String timeout = getProperty("DiscoverableTimeout"); 869d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (timeout != null) 870d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(timeout); 871d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 872d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return -1; 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getScanMode() { 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 8778c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) 878de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 879d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 880d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean pairable = getProperty("Pairable").equals("true"); 881d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean discoverable = getProperty("Discoverable").equals("true"); 882d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return bluezStringToScanMode (pairable, discoverable); 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 885d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean startDiscovery() { 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 8888c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 8898c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 890d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return startDiscoveryNative(); 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 893d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean cancelDiscovery() { 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 8968c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 8978c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 898d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return stopDiscoveryNative(); 899d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 900d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 901d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean isDiscovering() { 902d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 903d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return mIsDiscovering; 904d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 905d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 906d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ void setIsDiscovering(boolean isDiscovering) { 907d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mIsDiscovering = isDiscovering; 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 910cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private boolean isBondingFeasible(String address) { 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9138c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 9148c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 915005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9202092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (mBondState.getPendingOutgoingBonding() != null) { 9219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Ignoring createBond(): another device is bonding"); 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a different device is currently bonding, fail 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check for bond state only if we are not performing auto 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pairing exponential back-off attempts. 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mBondState.isAutoPairingAttemptsInProgress(address) && 929005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.getBondState(address) != BluetoothDevice.BOND_NONE) { 9309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Ignoring createBond(): this device is already bonding or bonded"); 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9343fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (address.equals(mDockAddress)) { 9353fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (!writeDockPin()) { 9369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "Error while writing Pin for the dock"); 9373fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 9383fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 9393fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 940cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return true; 941cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 9423fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 943cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean createBond(String address) { 944cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isBondingFeasible(address)) return false; 945cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 946cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!createPairedDeviceNative(address, 60000 /*1 minute*/ )) { 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9502092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mBondState.setPendingOutgoingBonding(address); 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); 9522092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 956cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean createBondOutOfBand(String address, byte[] hash, 957cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer) { 958cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isBondingFeasible(address)) return false; 9593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 960cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!createPairedDeviceOutOfBandNative(address, 60000 /* 1 minute */)) { 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 964cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh setDeviceOutOfBandData(address, hash, randomizer); 9652092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mBondState.setPendingOutgoingBonding(address); 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); 9672092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 971cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean setDeviceOutOfBandData(String address, byte[] hash, 972cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer) { 973cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 974cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 975cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return false; 976cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 977cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair <byte[], byte[]> value = new Pair<byte[], byte[]>(hash, randomizer); 978cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 979cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (DBG) { 9809a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Setting out of band data for: " + address + ":" + 9819a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Arrays.toString(hash) + ":" + Arrays.toString(randomizer)); 982cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 983cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 984cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mDeviceOobData.put(address, value); 985cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return true; 986cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 987cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 988cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair<byte[], byte[]> getDeviceOutOfBandData(BluetoothDevice device) { 989cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return mDeviceOobData.get(device.getAddress()); 990cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 991cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 992cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 993cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized byte[] readOutOfBandData() { 994cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 995cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH permission"); 996cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return null; 997cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 998cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return readAdapterOutOfBandDataNative(); 999cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1000cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean cancelBondProcess(String address) { 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 10048c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 10058c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1006005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) { 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1014005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 1016d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh cancelDeviceCreationNative(address); 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean removeBond(String address) { 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 10238c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 10248c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1025005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1028f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 10299b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 1030f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh state.sendMessage(BluetoothDeviceProfileState.UNPAIR); 10319b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 10329b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } else { 10339b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 10349b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 10359b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 10369b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 10379b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public synchronized boolean removeBondInternal(String address) { 1038cc2c06656ceafbcd91ec5b679aa6c9eae0d9982cJaikumar Ganesh // Unset the trusted device state and then unpair 1039cc2c06656ceafbcd91ec5b679aa6c9eae0d9982cJaikumar Ganesh setTrust(address, false); 1040d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return removeDeviceNative(getObjectPathFromAddress(address)); 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized String[] listBonds() { 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.listInState(BluetoothDevice.BOND_BONDED); 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1048a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized String[] listInState(int state) { 1049a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return mBondState.listInState(state); 1050a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1051a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getBondState(String address) { 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1054005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1055b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.getBondState(address.toUpperCase()); 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1060a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean setBondState(String address, int state) { 1061a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return setBondState(address, state, 0); 1062a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1063a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 1064a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean setBondState(String address, int state, int reason) { 1065ae5fbb0b4363a2a399e92e310777d7a955a25370Arek Lichwa mBondState.setBondState(address.toUpperCase(), state, reason); 1066a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return true; 1067a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1068a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 10693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh public synchronized boolean isBluetoothDock(String address) { 10706e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 10719a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Context.MODE_PRIVATE); 10726e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 10736e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh return sp.contains(SHARED_PREFERENCE_DOCK_ADDRESS + address); 10743fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 10753fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 10769488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh /*package*/ String[] getRemoteDeviceProperties(String address) { 10778c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return null; 10788c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 10799488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh String objectPath = getObjectPathFromAddress(address); 10809488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh return (String [])getDevicePropertiesNative(objectPath); 10819488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 10829488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1084efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Sets the remote device trust state. 1085efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 1086efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * @return boolean to indicate operation success or fail 1087efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1088efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean setTrust(String address, boolean value) { 1089005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1090e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1091e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly "Need BLUETOOTH_ADMIN permission"); 1092efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1093efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1094efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 10958c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 10968c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 10979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return setDevicePropertyBooleanNative( 10989a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby getObjectPathFromAddress(address), "Trusted", value ? 1 : 0); 1099efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1100efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1101efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1102efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Gets the remote device trust state as boolean. 1103efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Note: this value may be 1104efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * retrieved from cache if we retrieved the data before * 1105efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 11069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @return boolean to indicate trusted or untrusted state 1107efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1108efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean getTrustState(String address) { 1109005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1110efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1111efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1112efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1113efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 11149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = mDeviceProperties.getProperty(address, "Trusted"); 1115efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue if (val == null) { 1116efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1117efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } else { 11189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return val.equals("true"); 1119efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1120efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1121efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1122efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1123d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the remote major, minor classes encoded as a 32-bit 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * integer. 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: this value is retrieved from cache, because we get it during 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * remote-device discovery. 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return 32-bit integer encoding the remote major, minor, and service 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * classes. 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getRemoteClass(String address) { 1133005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1134ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1135ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly return BluetoothClass.ERROR; 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = mDeviceProperties.getProperty(address, "Class"); 1138d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (val == null) 1139d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return BluetoothClass.ERROR; 1140d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else { 1141d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(val); 1142d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1144d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1147dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * Gets the UUIDs supported by the remote device 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1149dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @return array of 128bit ParcelUuids 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1151dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public synchronized ParcelUuid[] getRemoteUuids(String address) { 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1153005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11561caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return getUuidFromCache(address); 11571caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 11581caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 11599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid[] getUuidFromCache(String address) { 11609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String value = mDeviceProperties.getProperty(address, "UUIDs"); 1161dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh if (value == null) return null; 1162dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1163dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh String[] uuidStrings = null; 1164d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The UUIDs are stored as a "," separated string. 1165dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuidStrings = value.split(","); 1166dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; 1167dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1168dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh for (int i = 0; i < uuidStrings.length; i++) { 1169dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuids[i] = ParcelUuid.fromString(uuidStrings[i]); 1170dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh } 1171d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return uuids; 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 117416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** 117516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Connect and fetch new UUID's using SDP. 117616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * The UUID's found are broadcast as intents. 117716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Optionally takes a uuid and callback to fetch the RFCOMM channel for the 117816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * a given uuid. 117916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to broadcast UUID intents on success 118016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to handle the failure case for 118116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * callback and broadcast intents. 118216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly */ 118316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public synchronized boolean fetchRemoteUuids(String address, ParcelUuid uuid, 118416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback) { 11851caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 11868c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11878c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 11881caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11891caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return false; 11901caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 11911caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 119216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = new RemoteService(address, uuid); 119316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null && mUuidCallbackTracker.get(service) != null) { 119416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // An SDP query for this address & uuid is already in progress 119516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Do not add this callback for the uuid 119616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 119716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 119816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 11991caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (mUuidIntentTracker.contains(address)) { 12001caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // An SDP query for this address is already in progress 120116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Add this uuid onto the in-progress SDP query 120216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 120316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 120416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 12051caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return true; 12061caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12071caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 1208421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh // If the device is already created, we will 1209421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh // do the SDP on the callback of createDeviceNative. 1210421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh boolean ret= createDeviceNative(address); 12111caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12121caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker.add(address); 121316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 121416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 121516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 12161caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12171caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT); 12181caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh message.obj = address; 12191caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY); 12201caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return ret; 12211caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12221caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1224d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the rfcomm channel associated with the UUID. 122516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Pulls records from the cache only. 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1227d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Address of the remote device 1228dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @param uuid ParcelUuid of the service attribute 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1230d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return rfcomm channel associated with the service attribute 123110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh * -1 on error 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1233dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public int getRemoteServiceChannel(String address, ParcelUuid uuid) { 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 12358c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 12368c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1237005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1238b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 124010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // Check if we are recovering from a crash. 124110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (mDeviceProperties.isEmpty()) { 12429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (mDeviceProperties.updateCache(address) == null) 124310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 124410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 124510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 124610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address); 124710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (value != null && value.containsKey(uuid)) 124810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return value.get(uuid); 124910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setPin(String address, byte[] pin) { 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 12558c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 12568c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pin == null || pin.length <= 0 || pin.length > 16 || 1258005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly !BluetoothAdapter.checkBluetoothAddress(address)) { 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "setPin(" + address + ") called but no native data available, " + 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " or by bluez.\n"); 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bluez API wants pin as a string 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pinString; 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pinString = new String(pin, "UTF8"); 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (UnsupportedEncodingException uee) { 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "UTF8 not supported?!?"); 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return setPinNative(address, pinString, data.intValue()); 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1280b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPasskey(String address, int passkey) { 1281b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1282b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 12838c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 12848c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1285005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (passkey < 0 || passkey > 999999 || !BluetoothAdapter.checkBluetoothAddress(address)) { 1286b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1287b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1288b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1289b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1290b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1291b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1292b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1293b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1294b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1295b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1296b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPasskeyNative(address, passkey, data.intValue()); 1297b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1298b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1299b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPairingConfirmation(String address, boolean confirm) { 1300b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1301b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 13028c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13038c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1304b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1305b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1306b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1307b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1308b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1309b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1310b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1311b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1312b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPairingConfirmationNative(address, confirm, data.intValue()); 1313b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1314b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1315cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean setRemoteOutOfBandData(String address) { 1316cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1317cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 1318cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return false; 1319cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh address = address.toUpperCase(); 1320cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1321cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (data == null) { 1322cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Log.w(TAG, "setRemoteOobData(" + address + ") called but no native data available, " + 1323cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1324cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh " or by bluez.\n"); 1325cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return false; 1326cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1327cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1328cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair<byte[], byte[]> val = mDeviceOobData.get(address); 1329cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] hash, randomizer; 1330cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (val == null) { 1331cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh // TODO: check what should be passed in this case. 1332cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh hash = new byte[16]; 1333cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh randomizer = new byte[16]; 1334cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } else { 1335cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh hash = val.first; 1336cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh randomizer = val.second; 1337cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1338cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return setRemoteOutOfBandDataNative(address, hash, randomizer, data.intValue()); 1339cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1340cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1341b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean cancelPairingUserInput(String address) { 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 13448c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13458c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1346005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1349005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 1350397d8f4f4829a45f4fe7a672cc395466bbc0f442Jaikumar Ganesh BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 1354b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "cancelUserInputNative(" + address + ") called but no native data " + 1355b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "available, ignoring. Maybe the PasskeyAgent Request was already cancelled " + 1356b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "by the remote or by bluez.\n"); 13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1359b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return cancelPairingUserInputNative(address, data.intValue()); 13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13628c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh /*package*/ void updateDeviceServiceChannelCache(String address) { 13639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "updateDeviceServiceChannelCache(" + address + ")"); 13649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 136510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // We are storing the rfcomm channel numbers only for the uuids 136610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // we are interested in. 13679a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid[] deviceUuids = getRemoteUuids(address); 136816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 13699a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ArrayList<ParcelUuid> applicationUuids = new ArrayList<ParcelUuid>(); 137016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 137116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 137216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (RemoteService service : mUuidCallbackTracker.keySet()) { 137316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 137416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly applicationUuids.add(service.uuid); 137516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 137616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 137716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 137810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 13799a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Map <ParcelUuid, Integer> uuidToChannelMap = new HashMap<ParcelUuid, Integer>(); 138016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 138116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for default uuids 138216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : RFCOMM_UUIDS) { 138310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 13849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = getDeviceServiceChannelForUuid(address, uuid); 13859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuidToChannelMap.put(uuid, channel); 13869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "\tuuid(system): " + uuid + " " + channel); 138710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 138810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 138916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for application requested uuids 139016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : applicationUuids) { 139116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 13929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = getDeviceServiceChannelForUuid(address, uuid); 13939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuidToChannelMap.put(uuid, channel); 13949a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "\tuuid(application): " + uuid + " " + channel); 139516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 139616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 139716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 139816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 139916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Make application callbacks 140016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 140116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 140216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 140316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 14049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (uuidToChannelMap.containsKey(service.uuid)) { 14059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = uuidToChannelMap.get(service.uuid); 14069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 14079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Making callback for " + service.uuid + 14089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby " with result " + channel); 140916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 141016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 141116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 141216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(channel); 141316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 141416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 141516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 141616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 141716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 141816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 141916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 142016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 142116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Update cache 14229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceServiceChannelCache.put(address, uuidToChannelMap); 142316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 142410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 142510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 14269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private int getDeviceServiceChannelForUuid(String address, 14279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid uuid) { 14289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return getDeviceServiceChannelNative(getObjectPathFromAddress(address), 14299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuid.toString(), 0x0004); 14309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 14319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 143224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly /** 143324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * b is a handle to a Binder instance, so that this service can be notified 143424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * for Applications that terminate unexpectedly, to clean there service 143524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * records 143624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly */ 143724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid, 143824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int channel, IBinder b) { 14398c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 14408c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 14418c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 144224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (serviceName == null || uuid == null || channel < 1 || 144324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) { 144424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 144524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 144624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) { 144724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Log.w(TAG, "Attempted to register a reserved UUID: " + uuid); 144824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 144924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 145024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle = addRfcommServiceRecordNative(serviceName, 145124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(), 145224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly (short)channel); 14539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "new handle " + Integer.toHexString(handle)); 145424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (handle == -1) { 145524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 145624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 145724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 145824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int pid = Binder.getCallingPid(); 145924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.put(new Integer(handle), new Integer(pid)); 146024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly try { 146124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly b.linkToDeath(new Reaper(handle, pid), 0); 146224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } catch (RemoteException e) {} 146324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return handle; 146424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 146524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 146624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void removeServiceRecord(int handle) { 146724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 146824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly "Need BLUETOOTH permission"); 146924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly checkAndRemoveRecord(handle, Binder.getCallingPid()); 147024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 147124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 147224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private synchronized void checkAndRemoveRecord(int handle, int pid) { 147324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer handleInt = new Integer(handle); 147424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer owner = mServiceRecordToPid.get(handleInt); 147524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (owner != null && pid == owner.intValue()) { 14769a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Removing service record " + 14779a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Integer.toHexString(handle) + " for pid " + pid); 147824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.remove(handleInt); 147924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly removeServiceRecordNative(handle); 148024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 148124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 148224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 148324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private class Reaper implements IBinder.DeathRecipient { 148424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int pid; 148524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle; 148624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Reaper(int handle, int pid) { 148724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly this.pid = pid; 148824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly this.handle = handle; 148924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 149024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void binderDied() { 149124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly synchronized (BluetoothService.this) { 14929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Tracked app " + pid + " died"); 149324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly checkAndRemoveRecord(handle, pid); 149424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 149524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 149624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 149724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 15016e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (intent == null) return; 15026e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String action = intent.getAction(); 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver resolver = context.getContentResolver(); 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Query the airplane mode from Settings.System just to make sure that 15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // some random app is not sending this intent and disabling bluetooth 15087f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (isAirplaneModeOn()) { 15097f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_ON); 15107f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else { 15117f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_OFF); 15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15136e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else if (Intent.ACTION_DOCK_EVENT.equals(action)) { 15146e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 15156e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh Intent.EXTRA_DOCK_STATE_UNDOCKED); 15166e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (DBG) Log.v(TAG, "Received ACTION_DOCK_EVENT with State:" + state); 15176e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) { 15186e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockAddress = null; 15196e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockPin = null; 15206e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else { 15216e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences.Editor editor = 15226e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 15236e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.MODE_PRIVATE).edit(); 15246e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh editor.putBoolean(SHARED_PREFERENCE_DOCK_ADDRESS + mDockAddress, true); 152566fce5068a8a3aeb28aaf713843891b286a75280Brad Fitzpatrick editor.apply(); 15266e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } 15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15316e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private void registerForAirplaneMode(IntentFilter filter) { 153244303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final ContentResolver resolver = mContext.getContentResolver(); 153344303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String airplaneModeRadios = Settings.System.getString(resolver, 15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_RADIOS); 153544303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String toggleableRadios = Settings.System.getString(resolver, 153644303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 153744303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 153844303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneSensitive = airplaneModeRadios == null ? true : 153944303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH); 154044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneToggleable = toggleableRadios == null ? false : 154144303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH); 154244303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsAirplaneSensitive) { 15446e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Returns true if airplane mode is currently on */ 15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean isAirplaneModeOn() { 15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Settings.System.getInt(mContext.getContentResolver(), 15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_ON, 0) == 1; 15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15541caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /* Broadcast the Uuid intent */ 15551caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /*package*/ synchronized void sendUuidIntent(String address) { 15566179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh ParcelUuid[] uuid = getUuidFromCache(address); 15576179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_UUID); 15582d3b98d868cda30535505b2a2fba47aa1c9c052bJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 15596179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid); 15606179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 15619a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mUuidIntentTracker.remove(address); 156216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 156316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 156416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ synchronized void makeServiceChannelCallbacks(String address) { 156516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 156616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 156716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 156816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 15699a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Cleaning up failed UUID channel lookup: " 15709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + service.address + " " + service.uuid); 157116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 157216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 157316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 157416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(-1); 157516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 157616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 157716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 157816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 157916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 158016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 15811caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 15821caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 15857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) { 1586105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1587105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1588105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 158924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive); 159044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey pw.println("mIsAirplaneToggleable = " + mIsAirplaneToggleable); 159124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 159224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local address = " + getAddress()); 159324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local name = " + getName()); 159424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("isDiscovering() = " + isDiscovering()); 1595105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 159696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh mAdapter.getProfileProxy(mContext, 159796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.HEADSET); 15984ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mAdapter.getProfileProxy(mContext, 15994ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.INPUT_DEVICE); 160074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mAdapter.getProfileProxy(mContext, 160174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.PAN); 1602105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 16039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpKnownDevices(pw); 16049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpAclConnectedDevices(pw); 16059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpHeadsetService(pw); 16064ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh dumpInputDeviceProfile(pw); 160774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh dumpPanProfile(pw); 16089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpApplicationServiceRecords(pw); 16094ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 16104ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 16119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpHeadsetService(PrintWriter pw) { 1612105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--Headset Service--"); 161396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (mBluetoothHeadset != null) { 1614bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices(); 1615bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh if (deviceList.size() == 0) { 161674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No headsets connected"); 1617bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh } else { 1618bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 16199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\ngetConnectedDevices[0] = " + device); 16209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpHeadsetConnectionState(pw, device); 1621bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh pw.println("getBatteryUsageHint() = " + 1622bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh mBluetoothHeadset.getBatteryUsageHint(device)); 162396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 162496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 16255a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh deviceList.clear(); 16265a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh deviceList = mBluetoothHeadset.getDevicesMatchingConnectionStates(new int[] { 162796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 162874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("--Connected and Disconnected Headsets"); 1629bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 163096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh pw.println(device); 163196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (mBluetoothHeadset.isAudioConnected(device)) { 163296a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh pw.println("SCO audio connected to device:" + device); 163396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 163496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 1635105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 16364ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); 16374ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 16386c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly 16394ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh private void dumpInputDeviceProfile(PrintWriter pw) { 16404ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("\n--Bluetooth Service- Input Device Profile"); 16414ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (mInputDevice != null) { 16424ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh List<BluetoothDevice> deviceList = mInputDevice.getConnectedDevices(); 16434ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (deviceList.size() == 0) { 164474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No input devices connected"); 16454ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else { 164674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("Number of connected devices:" + deviceList.size()); 16474ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 16484ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectedDevices[0] = " + device); 16494ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("Priority of Connected device = " + mInputDevice.getPriority(device)); 16504ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 16514ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh switch (mInputDevice.getConnectionState(device)) { 16524ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTING: 16534ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTING"); 16544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 16554ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTED: 16564ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTED"); 16574ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 16584ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_DISCONNECTING: 16594ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_DISCONNECTING"); 16604ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 16614ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 16624ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 16634ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh deviceList.clear(); 16644ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh deviceList = mInputDevice.getDevicesMatchingConnectionStates(new int[] { 16654ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 16664ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("--Connected and Disconnected input devices"); 16674ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 16684ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println(device); 16694ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 167024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 16714ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mAdapter.closeProfileProxy(BluetoothProfile.INPUT_DEVICE, mBluetoothHeadset); 16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 167474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private void dumpPanProfile(PrintWriter pw) { 167574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("\n--Bluetooth Service- Pan Profile"); 167674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (mPan != null) { 167774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh List<BluetoothDevice> deviceList = mPan.getConnectedDevices(); 167874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (deviceList.size() == 0) { 167974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No Pan devices connected"); 168074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else { 168174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("Number of connected devices:" + deviceList.size()); 168274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 168374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectedDevices[0] = " + device); 168474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 168574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh switch (mPan.getConnectionState(device)) { 168674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTING: 168774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTING"); 168874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 168974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTED: 169074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTED"); 169174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 169274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_DISCONNECTING: 169374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_DISCONNECTING"); 169474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 169574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 169674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 169774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh deviceList.clear(); 169874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh deviceList = mPan.getDevicesMatchingConnectionStates(new int[] { 169974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 170074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("--Connected and Disconnected Pan devices"); 170174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 170274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println(device); 170374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 170474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 17059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 17079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpHeadsetConnectionState(PrintWriter pw, 17089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDevice device) { 17099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby switch (mBluetoothHeadset.getConnectionState(device)) { 17109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_CONNECTING: 17119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_CONNECTING"); 17129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 17139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_CONNECTED: 17149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_CONNECTED"); 17159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 17169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_DISCONNECTING: 17179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_DISCONNECTING"); 17189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 17199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_AUDIO_CONNECTED: 17209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_AUDIO_CONNECTED"); 17219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 17229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 17259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpApplicationServiceRecords(PrintWriter pw) { 17269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--Application Service Records--"); 17279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (Integer handle : mServiceRecordToPid.keySet()) { 17289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Integer pid = mServiceRecordToPid.get(handle); 17299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle)); 17309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 173174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mAdapter.closeProfileProxy(BluetoothProfile.PAN, mBluetoothHeadset); 173274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 173374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 17349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpAclConnectedDevices(PrintWriter pw) { 17359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] devicesObjectPath = getKnownDevices(); 17369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--ACL connected devices--"); 17379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (devicesObjectPath != null) { 17389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String device : devicesObjectPath) { 17399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println(getAddressFromObjectPath(device)); 17409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 17449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpKnownDevices(PrintWriter pw) { 17459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--Known devices--"); 17469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String address : mDeviceProperties.keySet()) { 17479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int bondState = mBondState.getBondState(address); 17489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.printf("%s %10s (%d) %s\n", address, 17499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby toBondStateString(bondState), 17509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mBondState.getAttempt(address), 17519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby getRemoteName(address)); 17529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 17539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Map<ParcelUuid, Integer> uuidChannels = mDeviceServiceChannelCache.get(address); 17549a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (uuidChannels == null) { 17559a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tuuids = null"); 17569a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } else { 17579a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (ParcelUuid uuid : uuidChannels.keySet()) { 17589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Integer channel = uuidChannels.get(uuid); 17599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (channel == null) { 17609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\t" + uuid); 17619a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } else { 17629a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\t" + uuid + " RFCOMM channel = " + channel); 17639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17669a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (RemoteService service : mUuidCallbackTracker.keySet()) { 17679a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (service.address.equals(address)) { 17689a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tPENDING CALLBACK: " + service.uuid); 17699a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17719a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17729a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17739a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 177496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 177596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh new BluetoothProfile.ServiceListener() { 177696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh public void onServiceConnected(int profile, BluetoothProfile proxy) { 17774ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (profile == BluetoothProfile.HEADSET) { 17784ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mBluetoothHeadset = (BluetoothHeadset) proxy; 17794ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else if (profile == BluetoothProfile.INPUT_DEVICE) { 17804ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mInputDevice = (BluetoothInputDevice) proxy; 178174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else if (profile == BluetoothProfile.PAN) { 178274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mPan = (BluetoothPan) proxy; 17834ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 17844ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 178596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh public void onServiceDisconnected(int profile) { 17864ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (profile == BluetoothProfile.HEADSET) { 17874ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mBluetoothHeadset = null; 17884ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else if (profile == BluetoothProfile.INPUT_DEVICE) { 17894ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mInputDevice = null; 179074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else if (profile == BluetoothProfile.PAN) { 179174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mPan = null; 17924ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 179396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 179496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh }; 179596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 1796d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) { 1797d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (pairable && discoverable) 1798bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1799d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else if (pairable && !discoverable) 1800bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 1801d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 1802bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static String scanModeToBluezString(int mode) { 18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mode) { 1807bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "off"; 1809bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "connectable"; 1811bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "discoverable"; 18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1817d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getAddressFromObjectPath(String objectPath) { 18189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String adapterObjectPath = mAdapterProperties.getObjectPath(); 1819d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (adapterObjectPath == null || objectPath == null) { 1820f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath + 1821d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " or deviceObjectPath:" + objectPath + " is null"); 1822d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1823d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1824d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!objectPath.startsWith(adapterObjectPath)) { 1825f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath + 1826d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " is not a prefix of deviceObjectPath:" + objectPath + 1827d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh "bluetoothd crashed ?"); 1828d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1829d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1830d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String address = objectPath.substring(adapterObjectPath.length()); 1831d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (address != null) return address.replace('_', ':'); 1832d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1833d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: Address being returned is null"); 1834d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1835d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1836d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1837d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getObjectPathFromAddress(String address) { 18389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String path = mAdapterProperties.getObjectPath(); 1839d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (path == null) { 1840d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "Error: Object Path is null"); 1841d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1842d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1843d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh path = path + address.replace(":", "_"); 1844d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return path; 1845d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1846d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1847b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh /*package */ void setLinkTimeout(String address, int num_slots) { 1848b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh String path = getObjectPathFromAddress(address); 1849b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh boolean result = setLinkTimeoutNative(path, num_slots); 1850b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 18519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (!result) Log.d(TAG, "Set Link Timeout to " + num_slots + " slots failed"); 1852b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh } 1853b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 185430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /**** Handlers for PAN Profile ****/ 18556003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh // TODO: This needs to be converted to a state machine. 185630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 18576003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean isTetheringOn() { 185830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 18596003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 18606003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.isTetheringOn(); 18616003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 186230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 186330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 18646003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/boolean allowIncomingTethering() { 18656003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 18666003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.allowIncomingTethering(); 18676003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 186830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 186930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 18706003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public void setBluetoothTethering(boolean value) { 187130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 18726003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 18736003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothPanProfileHandler.setBluetoothTethering(value); 18746003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 187530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 187630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 18776003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public int getPanDeviceConnectionState(BluetoothDevice device) { 187830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 18796003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 18806003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.getPanDeviceConnectionState(device); 18816003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 188230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 188330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 18846003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean connectPanDevice(BluetoothDevice device) { 188530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 188630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 18876003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 18886003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.connectPanDevice(device); 18896003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 189030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 189130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 18926003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getConnectedPanDevices() { 189330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 18946003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 18956003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.getConnectedPanDevices(); 18966003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 189730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 189830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 18996003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getPanDevicesMatchingConnectionStates( 190074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh int[] states) { 190174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 19026003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19036003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.getPanDevicesMatchingConnectionStates(states); 19046003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 190574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 190674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 19076003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean disconnectPanDevice(BluetoothDevice device) { 190830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 190930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 19106003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19116003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.disconnectPanDevice(device); 19126003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 191330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 191430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19156003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/void handlePanDeviceStateChange(BluetoothDevice device, 191630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh String iface, 191730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int state, 191830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int role) { 19196003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19206003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, iface, state, role); 19216003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 192230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 192330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19246003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/void handlePanDeviceStateChange(BluetoothDevice device, 192530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int state, int role) { 19266003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19276003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, null, state, role); 19286003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 192930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 193030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 193130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /**** Handlers for Input Device Profile ****/ 19326003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh // This needs to be converted to state machine 193330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19346003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean connectInputDevice(BluetoothDevice device) { 193530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 193630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 193730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress()); 19386003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 19396003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.connectInputDevice(device, state); 19406003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 194130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 194230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19436003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean connectInputDeviceInternal(BluetoothDevice device) { 19446003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 19456003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.connectInputDeviceInternal(device); 19466003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 194730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 194830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19496003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean disconnectInputDevice(BluetoothDevice device) { 195030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 195130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 195230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress()); 19536003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 19546003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.disconnectInputDevice(device, state); 19556003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 195630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 195730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19586003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean disconnectInputDeviceInternal(BluetoothDevice device) { 19596003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 19606003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device); 19616003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 196230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 196330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19646003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public int getInputDeviceConnectionState(BluetoothDevice device) { 196530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 19666003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 19676003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device); 19686003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 196930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 197030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19716003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getConnectedInputDevices() { 197230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 19736003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 19746003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getConnectedInputDevices(); 19756003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 197630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 197730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19786003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getInputDevicesMatchingConnectionStates( 19794ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh int[] states) { 19804ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 19816003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 19826003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states); 19836003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 19844ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 19854ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 19864ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 19876003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public int getInputDevicePriority(BluetoothDevice device) { 198830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 19896003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 19906003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getInputDevicePriority(device); 19916003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 199230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 199330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19946003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean setInputDevicePriority(BluetoothDevice device, int priority) { 199530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 199630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 19976003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 19986003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.setInputDevicePriority(device, priority); 19996003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 200030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 200130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 2002a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie public boolean allowIncomingHidConnect(BluetoothDevice device, boolean allow) { 2003a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 2004a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie "Need BLUETOOTH_ADMIN permission"); 2005a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie String address = device.getAddress(); 2006a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (!BluetoothAdapter.checkBluetoothAddress(address)) { 2007a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return false; 2008a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2009a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2010a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Integer data = getAuthorizationAgentRequestData(address); 2011a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (data == null) { 2012a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Log.w(TAG, "allowIncomingHidConnect(" + device + 2013a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie ") called but no native data available"); 2014a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return false; 2015a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2016a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (DBG) log("allowIncomingHidConnect: " + device + " : " + allow + " : " + data); 2017a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return setAuthorizationNative(address, allow, data.intValue()); 2018a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2019a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 20206003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) { 20216003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 20226003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.lookupInputDevicesMatchingStates(states); 20236003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 202430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 202530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20266003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/void handleInputDevicePropertyChange(String address, boolean connected) { 20276003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 20286003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothInputProfileHandler.handleInputDevicePropertyChange(address, connected); 20296003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 203030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 203130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /**** Handlers for Health Device Profile ****/ 20332ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh // TODO: All these need to be converted to a state machine. 20342ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 2035fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config, 2036fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh IBluetoothHealthCallback callback) { 20372ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 20382ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 20392ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 2040fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh return mBluetoothHealthProfileHandler.registerAppConfiguration(config, callback); 20412ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20422ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20432ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 20442ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) { 20452ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 20462ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 20472ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 20482ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.unregisterAppConfiguration(config); 20492ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20502ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20512ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 20522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 20532ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean connectChannelToSource(BluetoothDevice device, 20542ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config) { 20552ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 20562ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 20572ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 20582ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.connectChannelToSource(device, 20592ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh config); 20602ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20612ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20622ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 20632ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean connectChannelToSink(BluetoothDevice device, 20642ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config, int channelType) { 20652ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 20662ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 20672ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 20682ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.connectChannel(device, config, 20692ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh channelType); 20702ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20712ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20722ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 20732ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean disconnectChannel(BluetoothDevice device, 20742ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) { 20752ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 20762ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 20772ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 20782ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.disconnectChannel(device, config, fd); 20792ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20802ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20812ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 20822ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device, 20832ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config) { 20842ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 20852ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 20862ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 20872ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.getMainChannelFd(device, config); 20882ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20892ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20902ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 20912ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /*package*/ void onHealthDevicePropertyChanged(String devicePath, 20922ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh String channelPath) { 20932ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 20942ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mBluetoothHealthProfileHandler.onHealthDevicePropertyChanged(devicePath, 20952ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh channelPath); 20962ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20972ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 20982ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 20992ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /*package*/ void onHealthDeviceChannelChanged(String devicePath, 21002ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh String channelPath, boolean exists) { 21012ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized(mBluetoothHealthProfileHandler) { 21022ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mBluetoothHealthProfileHandler.onHealthDeviceChannelChanged(devicePath, 21032ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh channelPath, exists); 21042ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21052ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21062ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21072ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public int getHealthDeviceConnectionState(BluetoothDevice device) { 21082ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 21092ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 21102ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 21112ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.getHealthDeviceConnectionState(device); 21122ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21132ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21142ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21152ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public List<BluetoothDevice> getConnectedHealthDevices() { 21162ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 21172ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 21182ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 21192ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.getConnectedHealthDevices(); 21202ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21212ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21222ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21232ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public List<BluetoothDevice> getHealthDevicesMatchingConnectionStates( 21242ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh int[] states) { 21252ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 21262ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 21272ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 21282ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler. 21292ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh getHealthDevicesMatchingConnectionStates(states); 21302ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21312ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 2133a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /*package*/boolean notifyIncomingHidConnection(String address) { 2134a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 2135a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (state == null) { 2136a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return false; 2137a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2138a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Message msg = new Message(); 2139a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie msg.what = BluetoothDeviceProfileState.CONNECT_HID_INCOMING; 2140a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie state.sendMessage(msg); 2141a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return true; 2142a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2143a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 21449b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectHeadset(String address) { 214596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 214696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2147f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 21489b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2149f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2150f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING; 2151f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2152f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.sendMessage(msg); 2153f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh return true; 21549b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21559b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 21569b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21579b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21589b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectHeadset(String address) { 215996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 216096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2161f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 21629b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2163f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2164f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HFP_OUTGOING; 2165f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2166f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.sendMessage(msg); 21679b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 21689b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21699b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 21709b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21719b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21729b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectSink(String address) { 217396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 217496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2175f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 21769b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2177f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2178f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING; 2179f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2180f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.sendMessage(msg); 2181f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh return true; 21829b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21839b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 21849b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21859b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 21869b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectSink(String address) { 218796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 218896a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2189f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 21909b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2191f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2192f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_A2DP_OUTGOING; 2193f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2194f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.sendMessage(msg); 21959b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 21969b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21979b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 21989b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 21999b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDeviceProfileState addProfileState(String address) { 2201f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 22029b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) return state; 22039b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 2204f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh state = new BluetoothDeviceProfileState(mContext, address, this, mA2dpService); 2205f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.put(address, state); 22069b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.start(); 22079b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return state; 22089b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22099b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void removeProfileState(String address) { 2211f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.remove(address); 22129b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22139b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby synchronized String[] getKnownDevices() { 22159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = null; 22169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = getProperty("Devices"); 22179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (val != null) { 22189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby bonds = val.split(","); 22199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 22209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return bonds; 22219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 22229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 22239b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private void initProfileState() { 22249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = null; 22259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = mAdapterProperties.getProperty("Devices"); 22269b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (val != null) { 22279b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh bonds = val.split(","); 22289b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22299b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (bonds == null) { 22309b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return; 22319b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22329b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh for (String path : bonds) { 22339b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh String address = getAddressFromObjectPath(path); 2234f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = addProfileState(address); 22359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 22369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 22379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 22389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void autoConnect() { 22399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = getKnownDevices(); 22409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (bonds == null) { 22419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return; 22429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 22439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String path : bonds) { 22449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String address = getAddressFromObjectPath(path); 22459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 22469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (state != null) { 22479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Message msg = new Message(); 22489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby msg.what = BluetoothDeviceProfileState.AUTO_CONNECT_PROFILES; 22499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state.sendMessage(msg); 22509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 22519b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22529b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22539b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22549b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean notifyIncomingConnection(String address) { 2255f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = 2256f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.get(address); 22579b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 22589b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 2259f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.what = BluetoothDeviceProfileState.CONNECT_HFP_INCOMING; 22609b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(msg); 22619b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 22629b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22639b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 22649b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22659b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22669b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /*package*/ boolean notifyIncomingA2dpConnection(String address) { 2267f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = 2268f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.get(address); 22699b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 22709b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 2271f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.what = BluetoothDeviceProfileState.CONNECT_A2DP_INCOMING; 22729b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(msg); 22739b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 22749b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22759b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 22769b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22779b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22789b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /*package*/ void setA2dpService(BluetoothA2dpService a2dpService) { 22799b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh mA2dpService = a2dpService; 22809b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22819b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 2282a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /*package*/ Integer getAuthorizationAgentRequestData(String address) { 2283a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Integer data = mEventLoop.getAuthorizationAgentRequestData().remove(address); 2284a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return data; 2285a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2286a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 228770a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh public void sendProfileStateMessage(int profile, int cmd) { 228870a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh Message msg = new Message(); 228970a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh msg.what = cmd; 229070a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh if (profile == BluetoothProfileState.HFP) { 229170a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh mHfpProfileState.sendMessage(msg); 229270a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } else if (profile == BluetoothProfileState.A2DP) { 229370a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh mA2dpProfileState.sendMessage(msg); 229470a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } 229570a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } 229670a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh 2297c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh public int getAdapterConnectionState() { 2298c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh return mAdapterConnectionState; 2299c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh } 2300c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 2301a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh public synchronized void sendConnectionStateChange(BluetoothDevice device, int state, 2302a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh int prevState) { 23039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Since this is a binder call check if Bluetooth is on still 23047f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return; 23059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 23069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (updateCountersAndCheckForConnectionStateChange(state, prevState)) { 23079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (!validateProfileConnectionState(state) || 23089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby !validateProfileConnectionState(prevState)) { 23099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Previously, an invalid state was broadcast anyway, 23109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // with the invalid state converted to -1 in the intent. 23119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Better to log an error and not send an intent with 23129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // invalid contents or set mAdapterConnectionState to -1. 23139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "Error in sendConnectionStateChange: " 23149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + "prevState " + prevState + " state " + state); 23159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return; 23169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 2317c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 2318c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh mAdapterConnectionState = state; 2319c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 23207f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (state == BluetoothProfile.STATE_DISCONNECTED) { 23217f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.ALL_DEVICES_DISCONNECTED); 23227f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 23237f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 2324a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 2325a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 23269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 23279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby convertToAdapterState(state)); 23289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, 23299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby convertToAdapterState(prevState)); 233060b4d2a2bd232a7116fd037501cac704f328c0a1Jaikumar Ganesh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2331a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 23329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "CONNECTION_STATE_CHANGE: " + device + ": " 23339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + prevState + " -> " + state); 2334a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2335a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2336a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 23379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private boolean validateProfileConnectionState(int state) { 23389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (state == BluetoothProfile.STATE_DISCONNECTED || 23399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_CONNECTING || 23409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_CONNECTED || 23419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_DISCONNECTING); 23429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 23439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 23449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private int convertToAdapterState(int state) { 2345a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh switch (state) { 23469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_DISCONNECTED: 23479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_DISCONNECTED; 23489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_DISCONNECTING: 23499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_DISCONNECTING; 23509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_CONNECTED: 23519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_CONNECTED; 2352a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTING: 2353a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh return BluetoothAdapter.STATE_CONNECTING; 23549a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 23559a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "Error in convertToAdapterState"); 23569a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return -1; 23579a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 23589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 23599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) { 23609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby switch (prevState) { 23619a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_CONNECTING: 23629a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesConnecting--; 23639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 23649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 2365a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTED: 23669a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesConnected--; 23679a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 23689a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 2369a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTING: 23709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesDisconnecting--; 23719a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 2372a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2373a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2374a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh switch (state) { 2375a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTING: 2376a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnecting++; 23779a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesConnecting == 1); 2378a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2379a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTED: 2380a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnected++; 23819a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 1); 2382a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2383a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTING: 2384a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesDisconnecting++; 23859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesDisconnecting == 1); 2386a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2387a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTED: 23889a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesConnecting == 0); 2389a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 23909a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby default: 23919a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return true; 2392a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 23939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2394d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2395a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private void createIncomingConnectionStateFile() { 2396a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie File f = new File(INCOMING_CONNECTION_FILE); 2397a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (!f.exists()) { 2398a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2399a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie f.createNewFile(); 2400a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2401a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Log.e(TAG, "IOException: cannot create file"); 2402a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2403a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2404a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2405a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2406a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /** @hide */ 2407a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie public Pair<Integer, String> getIncomingState(String address) { 2408a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (mIncomingConnections.isEmpty()) { 2409a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie createIncomingConnectionStateFile(); 2410a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie readIncomingConnectionState(); 2411a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2412a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return mIncomingConnections.get(address); 2413a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2414a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2415a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private void readIncomingConnectionState() { 2416a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie synchronized(mIncomingConnections) { 2417a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie FileInputStream fstream = null; 2418a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2419a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie fstream = new FileInputStream(INCOMING_CONNECTION_FILE); 2420a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie DataInputStream in = new DataInputStream(fstream); 2421a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie BufferedReader file = new BufferedReader(new InputStreamReader(in)); 2422a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie String line; 2423a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie while((line = file.readLine()) != null) { 2424a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie line = line.trim(); 2425a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (line.length() == 0) continue; 2426a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie String[] value = line.split(","); 2427a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (value != null && value.length == 3) { 2428a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Integer val1 = Integer.parseInt(value[1]); 2429a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Pair<Integer, String> val = new Pair(val1, value[2]); 2430a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mIncomingConnections.put(value[0], val); 2431a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2432a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2433a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (FileNotFoundException e) { 2434a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("FileNotFoundException: readIncomingConnectionState" + e.toString()); 2435a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2436a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("IOException: readIncomingConnectionState" + e.toString()); 2437a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } finally { 2438a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (fstream != null) { 2439a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2440a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie fstream.close(); 2441a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2442a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie // Ignore 2443a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2444a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2445a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2446a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2447a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2448a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2449a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private void truncateIncomingConnectionFile() { 2450a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie RandomAccessFile r = null; 2451a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2452a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie r = new RandomAccessFile(INCOMING_CONNECTION_FILE, "rw"); 2453a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie r.setLength(0); 2454a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (FileNotFoundException e) { 2455a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("FileNotFoundException: truncateIncomingConnectionState" + e.toString()); 2456a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2457a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("IOException: truncateIncomingConnectionState" + e.toString()); 2458a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } finally { 2459a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (r != null) { 2460a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2461a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie r.close(); 2462a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2463a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie // ignore 2464a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2465a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2466a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2467a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2468a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2469a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /** @hide */ 2470a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie public void writeIncomingConnectionState(String address, Pair<Integer, String> data) { 2471a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie synchronized(mIncomingConnections) { 2472a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mIncomingConnections.put(address, data); 2473a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2474a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie truncateIncomingConnectionFile(); 2475a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie BufferedWriter out = null; 2476a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie StringBuilder value = new StringBuilder(); 2477a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2478a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie out = new BufferedWriter(new FileWriter(INCOMING_CONNECTION_FILE, true)); 2479a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie for (String devAddress: mIncomingConnections.keySet()) { 2480a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Pair<Integer, String> val = mIncomingConnections.get(devAddress); 2481a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(devAddress); 2482a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(","); 2483a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(val.first.toString()); 2484a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(","); 2485a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(val.second); 2486a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append("\n"); 2487a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2488a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie out.write(value.toString()); 2489a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (FileNotFoundException e) { 2490a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("FileNotFoundException: writeIncomingConnectionState" + e.toString()); 2491a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2492a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("IOException: writeIncomingConnectionState" + e.toString()); 2493a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } finally { 2494a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (out != null) { 2495a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2496a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie out.close(); 2497a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2498a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie // Ignore 2499a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2500a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2501a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2502a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2503a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2504a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2505a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private static void log(String msg) { 2506a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Log.d(TAG, msg); 2507a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2508a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2509d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native static void classInitNative(); 2510d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void initializeNativeDataNative(); 2511d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setupNativeDataNative(); 2512d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean tearDownNativeDataNative(); 2513d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void cleanupNativeDataNative(); 25149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ native String getAdapterPathNative(); 2515d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2516d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int isEnabledNative(); 25177f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ native int enableNative(); 25187f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ native int disableNative(); 2519d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 25209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ native Object[] getAdapterPropertiesNative(); 2521d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native Object[] getDevicePropertiesNative(String objectPath); 2522d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyStringNative(String key, String value); 2523d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyIntegerNative(String key, int value); 2524d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyBooleanNative(String key, int value); 2525d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2526d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean startDiscoveryNative(); 2527d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean stopDiscoveryNative(); 2528d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2529d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean createPairedDeviceNative(String address, int timeout_ms); 2530cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native boolean createPairedDeviceOutOfBandNative(String address, int timeout_ms); 2531cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native byte[] readAdapterOutOfBandDataNative(); 2532cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 2533d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean cancelDeviceCreationNative(String address); 2534d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean removeDeviceNative(String objectPath); 2535d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int getDeviceServiceChannelNative(String objectPath, String uuid, 2536d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh int attributeId); 2537d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2538b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean cancelPairingUserInputNative(String address, int nativeData); 2539d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setPinNative(String address, String pin, int nativeData); 2540b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPasskeyNative(String address, int passkey, int nativeData); 2541b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPairingConfirmationNative(String address, boolean confirm, 2542b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh int nativeData); 2543cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native boolean setRemoteOutOfBandDataNative(String address, byte[] hash, 2544cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer, int nativeData); 2545cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 254624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean setDevicePropertyBooleanNative(String objectPath, String key, 254724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int value); 25481caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private native boolean createDeviceNative(String address); 254916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ native boolean discoverServicesNative(String objectPath, String pattern); 255010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 255124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb, 255224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly short channel); 255324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean removeServiceRecordNative(int handle); 2554b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh private native boolean setLinkTimeoutNative(String path, int num_slots); 2555a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 255630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh native boolean connectInputDeviceNative(String path); 255730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh native boolean disconnectInputDeviceNative(String path); 25586fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 2559a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge); 2560a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean connectPanDeviceNative(String path, String dstRole); 2561a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean disconnectPanDeviceNative(String path); 2562a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean disconnectPanServerDeviceNative(String path, 2563a44a1e77ef435942b2ff60e9e60d3a64b43d775bJaikumar Ganesh String address, String iface); 256484690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh 256584690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private native int[] addReservedServiceRecordsNative(int[] uuuids); 256684690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private native boolean removeReservedServiceRecordsNative(int[] handles); 25672ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 25682ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh // Health API 25692ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String registerHealthApplicationNative(int dataType, String role, String name, 25702ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh String channelType); 25712ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String registerHealthApplicationNative(int dataType, String role, String name); 25722ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native boolean unregisterHealthApplicationNative(String path); 25732ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native boolean createChannelNative(String devicePath, String appPath, String channelType); 25742ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native boolean destroyChannelNative(String devicePath, String channelpath); 25752ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String getMainChannelNative(String path); 25762ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String getChannelApplicationNative(String channelPath); 25772ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native ParcelFileDescriptor getChannelFdNative(String channelPath); 25782ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native boolean releaseChannelFdNative(String channelPath); 2579a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie native boolean setAuthorizationNative(String address, boolean value, int data); 25809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2581