BluetoothService.java revision ef2cb7c93a99096799d415e721dda46d1bf7a005
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; 42ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganeshimport android.bluetooth.IBluetoothStateChangeCallback; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 486e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganeshimport android.content.SharedPreferences; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 513fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.IBinder; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 532ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.os.ParcelFileDescriptor; 543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.ParcelUuid; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 56105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.os.ServiceManager; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 59cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganeshimport android.util.Pair; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 61fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganeshimport com.android.internal.app.IBatteryStats; 62fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh 633fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedInputStream; 64a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.BufferedReader; 653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedWriter; 66a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.DataInputStream; 67a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.File; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileInputStream; 703fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileNotFoundException; 713fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileWriter; 723fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.IOException; 73ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganeshimport java.io.InputStreamReader; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 75a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.RandomAccessFile; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.UnsupportedEncodingException; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays; 79ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganeshimport java.util.Collection; 80ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganeshimport java.util.Collections; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 8216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport java.util.Iterator; 835a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 86bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellypublic class BluetoothService extends IBluetooth.Stub { 87bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private static final String TAG = "BluetoothService"; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean DBG = true; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNativeData; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BluetoothEventLoop mEventLoop; 9296a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh private BluetoothHeadset mBluetoothHeadset; 934ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh private BluetoothInputDevice mInputDevice; 9474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private BluetoothPan mPan; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsAirplaneSensitive; 9644303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey private boolean mIsAirplaneToggleable; 977f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private BluetoothAdapterStateMachine mBluetoothState; 98997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly private boolean mRestart = false; // need to call enable() after disable() 99bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private boolean mIsDiscovering; 10084690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private int[] mAdapterSdpHandles; 10150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private ParcelUuid[] mAdapterUuids; 102997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 103bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private BluetoothAdapter mAdapter; // constant after init() 1049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothBondState mBondState; // local cache of bondings 105105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private final IBatteryStats mBatteryStats; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 107ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh private Map<Integer, IBluetoothStateChangeCallback> mStateChangeTracker = 108ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh Collections.synchronizedMap(new HashMap<Integer, IBluetoothStateChangeCallback>()); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 111a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1133fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_ADDRESS_PATH = "/sys/class/switch/dock/bt_addr"; 1143fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_PIN_PATH = "/sys/class/switch/dock/bt_pin"; 1153fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1166e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address"; 1176e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings"; 1186e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 1197f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private static final int MESSAGE_UUID_INTENT = 1; 1207f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 2; 121a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 122ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh private static final int RFCOMM_RECORD_REAPER = 10; 123ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh private static final int STATE_CHANGE_REAPER = 11; 124ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 125a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // The time (in millisecs) to delay the pairing attempt after the first 126a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // auto pairing attempt fails. We use an exponential delay with 127a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and 128a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value. 129a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000; 130a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000; 1311caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 1321caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // The timeout used to sent the UUIDs Intent 1331caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // This timeout should be greater than the page timeout 1341caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private static final int UUID_INTENT_DELAY = 6000; 135105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 13616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** Always retrieve RFCOMM channel for these SDP UUIDs */ 13716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static final ParcelUuid[] RFCOMM_UUIDS = { 13816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.Handsfree, 13916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.HSP, 14016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.ObexObjectPush }; 14116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothAdapterProperties mAdapterProperties; 1439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothDeviceProperties mDeviceProperties; 144d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 14516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache; 14616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final ArrayList<String> mUuidIntentTracker; 14716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker; 1481caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 14924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private final HashMap<Integer, Integer> mServiceRecordToPid; 15024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 151f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState; 152f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final BluetoothProfileState mA2dpProfileState; 153f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final BluetoothProfileState mHfpProfileState; 1549b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 1559b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private BluetoothA2dpService mA2dpService; 156cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData; 157545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 158a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh private int mProfilesConnected = 0, mProfilesConnecting = 0, mProfilesDisconnecting = 0; 159707952ecd4b6cae25aabcf51f94d702a65847e9eJaikumar Ganesh 1603fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static String mDockAddress; 1613fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private String mDockPin; 1623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 163c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED; 164a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh private BluetoothPanProfileHandler mBluetoothPanProfileHandler; 16530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh private BluetoothInputProfileHandler mBluetoothInputProfileHandler; 1662ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private BluetoothHealthProfileHandler mBluetoothHealthProfileHandler; 167a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private static final String INCOMING_CONNECTION_FILE = 168a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie "/data/misc/bluetooth/incoming_connection.conf"; 169a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private HashMap<String, Pair<Integer, String>> mIncomingConnections; 170c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 17116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static class RemoteService { 17216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public String address; 17316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public ParcelUuid uuid; 17416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public RemoteService(String address, ParcelUuid uuid) { 17516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.address = address; 17616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.uuid = uuid; 17716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 17816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly @Override 17916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public boolean equals(Object o) { 18016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (o instanceof RemoteService) { 18116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = (RemoteService)o; 18216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return address.equals(service.address) && uuid.equals(service.uuid); 18316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 18416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 18516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 1865f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root 1875f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root @Override 1885f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root public int hashCode() { 1895f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root int hash = 1; 1905f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (address == null ? 0 : address.hashCode()); 1915f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (uuid == null ? 0 : uuid.hashCode()); 1925f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root return hash; 1935f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root } 19416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 19516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project classInitNative(); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 200bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public BluetoothService(Context context) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 202105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 203105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Need to do this in place of: 204105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // mBatteryStats = BatteryStatsService.getService(); 205105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Since we can not import BatteryStatsService from here. This class really needs to be 206105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // moved to java/services/com/android/server/ 207105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initializeNativeDataNative(); 210ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 211ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (isEnabledNative() == 1) { 212ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Log.w(TAG, "Bluetooth daemons already running - runtime restart? "); 213ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project disableNative(); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 215ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsDiscovering = false; 217a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh 2189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mBondState = new BluetoothBondState(context, this); 2199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mAdapterProperties = new BluetoothAdapterProperties(context, this); 2209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties = new BluetoothDeviceProperties(this); 22110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 22210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>(); 223cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mDeviceOobData = new HashMap<String, Pair<byte[], byte[]>>(); 2241caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker = new ArrayList<String>(); 22516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>(); 22624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid = new HashMap<Integer, Integer>(); 227f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>(); 228f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP); 229f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP); 230f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh 231f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.start(); 232f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.start(); 2333fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2343fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh IntentFilter filter = new IntentFilter(); 2356e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh registerForAirplaneMode(filter); 2366e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 2373fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh filter.addAction(Intent.ACTION_DOCK_EVENT); 2386e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.registerReceiver(mReceiver, filter); 23930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this); 240a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this); 2412ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this); 242a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mIncomingConnections = new HashMap<String, Pair<Integer, String>>(); 2433fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2443fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2459b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public static synchronized String readDockBluetoothAddress() { 2463fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (mDockAddress != null) return mDockAddress; 2473fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2483fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedInputStream file = null; 2493fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh String dockAddress; 2503fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2513fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file = new BufferedInputStream(new FileInputStream(DOCK_ADDRESS_PATH)); 2523fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh byte[] address = new byte[17]; 2533fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.read(address); 2543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = new String(address); 2553fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = dockAddress.toUpperCase(); 2563fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (BluetoothAdapter.checkBluetoothAddress(dockAddress)) { 2573fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = dockAddress; 2583fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockAddress; 2593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } else { 2609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "CheckBluetoothAddress failed for car dock address: " 2619a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + dockAddress); 2623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2633fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "FileNotFoundException while trying to read dock address"); 2653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2669a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "IOException while trying to read dock address"); 2673fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 2683fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (file != null) { 2693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2703fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.close(); 2713fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2723fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 2733fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2743fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2753fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2763fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = null; 2773fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return null; 2783fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2793fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2803fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private synchronized boolean writeDockPin() { 2813fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedWriter out = null; 2823fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2833fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out = new BufferedWriter(new FileWriter(DOCK_PIN_PATH)); 2843fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2853fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Generate a random 4 digit pin between 0000 and 9999 2863fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // This is not truly random but good enough for our purposes. 2873fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh int pin = (int) Math.floor(Math.random() * 10000); 2883fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2893fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = String.format("%04d", pin); 2903fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.write(mDockPin); 2913fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return true; 2923fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "FileNotFoundException while trying to write dock pairing pin"); 2943fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2959a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "IOException while while trying to write dock pairing pin"); 2963fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 2973fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (out != null) { 2983fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2993fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.close(); 3003fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 3013fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 3023fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 3033fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 3043fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 3053fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = null; 3063fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 3073fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 3083fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 3093fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh /*package*/ synchronized String getDockPin() { 3103fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockPin; 311bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly } 312bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly 313bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public synchronized void initAfterRegistration() { 314f242b7b931898856bcbcb7ec36cacf43098ba544Nick Pelly mAdapter = BluetoothAdapter.getDefaultAdapter(); 3157f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter); 3167f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.start(); 3177f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mEventLoop = mBluetoothState.getBluetoothEventLoop(); 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3207d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh public synchronized void initAfterA2dpRegistration() { 3217d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh mEventLoop.getProfileProxy(); 3227d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh } 3237d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 3266e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.unregisterReceiver(mReceiver); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cleanupNativeDataNative(); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isEnabled() { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 3368c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh return isEnabledInternal(); 3378c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh } 3388c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 3398c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh private boolean isEnabledInternal() { 3407f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return (getBluetoothStateInternal() == BluetoothAdapter.STATE_ON); 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 343105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public int getBluetoothState() { 344105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 3457f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return getBluetoothStateInternal(); 346105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 347105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int getBluetoothStateInternal() { 3497f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return mBluetoothState.getBluetoothAdapterState(); 3509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 351105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth and disable BT in settings. Returns true on success. 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean disable() { 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return disable(true); 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth. Returns true on success. 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 362e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly * @param saveSetting If true, persist the new setting 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean disable(boolean saveSetting) { 365e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3677f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie int adapterState = getBluetoothStateInternal(); 3687f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 3697f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie switch (adapterState) { 370de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_OFF: 371105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 372de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_ON: 373105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 374105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project default: 375105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return false; 376105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 3777a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh 3787f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_OFF, saveSetting); 379105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 380105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 381105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3827f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie synchronized void disconnectDevices() { 3837a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh // Disconnect devices handled by BluetoothService. 3847a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh for (BluetoothDevice device: getConnectedInputDevices()) { 3857a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh disconnectInputDevice(device); 3867a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 3877a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh 3887a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh for (BluetoothDevice device: getConnectedPanDevices()) { 3897a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh disconnectPanDevice(device); 3907a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 3917a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 392105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3937f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 3947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * The Bluetooth has been turned off, but hot. Do bonding, profile, 3957f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * and internal cleanup 3967f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 3977f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie synchronized void finishDisable() { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mark in progress bondings as cancelled 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) { 400005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4042d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh // Stop the profile state machine for bonded devices. 4052d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDED)) { 4062d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh removeProfileState(address); 4072d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh } 4082d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // update mode 410de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 411de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 414105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mIsDiscovering = false; 415bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.clear(); 41624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.clear(); 417105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 418a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnected = 0; 419a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnecting = 0; 420a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesDisconnecting = 0; 421c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED; 42250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids = null; 42350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterSdpHandles = null; 424a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 425105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Log bluetooth off to battery stats. 426105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project long ident = Binder.clearCallingIdentity(); 427105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project try { 428105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats.noteBluetoothOff(); 429105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } catch (RemoteException e) { 430105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } finally { 431105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Binder.restoreCallingIdentity(ident); 432105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 433997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 434997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (mRestart) { 435997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 436997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly enable(); 437997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4407f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 4417f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * power off Bluetooth 4427f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 4437f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie synchronized void shutoffBluetooth() { 4447f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie tearDownNativeDataNative(); 4457f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie disableNative(); 4467f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (mRestart) { 4477f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mRestart = false; 4487f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie enable(); 4497f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4507f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4517f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 452105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /** Bring up BT and persist BT on in settings */ 453105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public boolean enable() { 454105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return enable(true); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enable this Bluetooth device, asynchronously. 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This turns on/off the underlying hardware. 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 461105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @param saveSetting If true, persist the new state of BT in settings 462105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @return True on success (so far) 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 464105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public synchronized boolean enable(boolean saveSetting) { 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Airplane mode can prevent Bluetooth radio from being turned on. 46944303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4727f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting); 4737f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return true; 4747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4757f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 4767f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 4777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Turn on Bluetooth Module, Load firmware, and do all the preparation 4787f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * needed to get the Bluetooth Module ready but keep it not discoverable 4797f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * and not connectable. 4807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 4817f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /* package */ synchronized boolean prepareBluetooth() { 4827f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (!setupNativeDataNative()) { 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mIsDiscovering = false; 4867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 4877f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie switchConnectable(false); 4887f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie updateSdpRecords(); 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 492997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /** Forcibly restart Bluetooth if it is on */ 493997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /* package */ synchronized void restart() { 4947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) { 495997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly return; 496997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 497997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = true; 498997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (!disable(false)) { 499997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 500997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 501d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 502997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Handler mHandler = new Handler() { 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 5071caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh case MESSAGE_UUID_INTENT: 5081caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String address = (String)msg.obj; 50916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (address != null) { 5101caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh sendUuidIntent(address); 51116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly makeServiceChannelCallbacks(address); 51216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 5131caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh break; 514a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY: 515a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh address = (String)msg.obj; 5168adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh if (address == null) return; 5178adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh int attempt = mBondState.getAttempt(address); 5188adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh 5198adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh // Try only if attemps are in progress and cap it 2 attempts 5208adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh // The 2 attempts cap is a fail safe if the stack returns 5218adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh // an incorrect error code for bonding failures and if the pin 5228adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh // is entered wrongly twice we should abort. 5238adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh if (attempt > 0 && attempt <= 2) { 5248adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh mBondState.attempt(address); 525a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh createBond(address); 526a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 527a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 5288adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh if (attempt > 0) mBondState.clearPinAttempts(address); 529a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh break; 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 53450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) { 53550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh //Register SDP records. 53650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh int[] svcIdentifiers = new int[uuids.size()]; 53750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh for (int i = 0; i < uuids.size(); i++) { 53850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh svcIdentifiers[i] = BluetoothUuid.getServiceIdentifierFromParcelUuid(uuids.get(i)); 53950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 54050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterSdpHandles = addReservedServiceRecordsNative(svcIdentifiers); 54150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 542105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 54350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private synchronized void updateSdpRecords() { 54450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh ArrayList<ParcelUuid> uuids = new ArrayList<ParcelUuid>(); 54550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 54650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add the default records 54750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.HSP_AG); 54850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.ObexObjectPush); 54950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 55050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh if (mContext.getResources(). 55150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh getBoolean(com.android.internal.R.bool.config_voice_capable)) { 55250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.Handsfree_AG); 55350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.PBAP_PSE); 55450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 55550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 55650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add SDP records for profiles maintained by Android userspace 55750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh addReservedSdpRecords(uuids); 55850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 55950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Enable profiles maintained by Bluez userspace. 56074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE, 56174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothPanProfileHandler.NAP_BRIDGE); 56250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 56350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add SDP records for profiles maintained by Bluez userspace 56450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.AudioSource); 56550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.AvrcpTarget); 56650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.NAP); 56750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 56850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Cannot cast uuids.toArray directly since ParcelUuid is parcelable 56950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids = new ParcelUuid[uuids.size()]; 57050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh for (int i = 0; i < uuids.size(); i++) { 57150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids[i] = uuids.get(i); 57250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 57350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 57450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 5759efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh /** 5769efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * This function is called from Bluetooth Event Loop when onPropertyChanged 5779efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * for adapter comes in with UUID property. 5789efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * @param uuidsThe uuids of adapter as reported by Bluez. 5799efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh */ 5807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ synchronized void updateBluetoothState(String uuids) { 5817f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids); 5829efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh 5837f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (mAdapterUuids != null && 5847f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) { 5857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5897f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 5907f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * This method is called immediately after Bluetooth module is turned on. 5917f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * It starts auto-connection and places bluetooth on sign onto the battery 5927f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * stats 5937f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 5947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ void runBluetooth() { 5957f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mIsDiscovering = false; 5967f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBondState.readAutoPairingData(); 5977f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBondState.initBondState(); 5987f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie initProfileState(); 5997f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 6007f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie autoConnect(); 6017f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 6027f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // Log bluetooth on to battery stats. 6037f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie long ident = Binder.clearCallingIdentity(); 6047f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie try { 6057f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBatteryStats.noteBluetoothOn(); 6067f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } catch (RemoteException e) { 6077f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Log.e(TAG, "", e); 6087f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } finally { 6097f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Binder.restoreCallingIdentity(ident); 6107f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 613a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean attemptAutoPair(String address) { 614a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (!mBondState.hasAutoPairingFailed(address) && 615a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh !mBondState.isAutoPairingBlacklisted(address)) { 616a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.attempt(address); 617a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setPin(address, BluetoothDevice.convertPinToBytes("0000")); 618a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return true; 619a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 620a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return false; 621a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 622a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 623f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh /*package*/ synchronized boolean isFixedPinZerosAutoPairKeyboard(String address) { 624f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh // Check for keyboards which have fixed PIN 0000 as the pairing pin 625f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh return mBondState.isFixedPinZerosAutoPairKeyboard(address); 626f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh } 627f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh 628a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized void onCreatePairedDeviceResult(String address, int result) { 629a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (result == BluetoothDevice.BOND_SUCCESS) { 630a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_BONDED); 631a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (mBondState.isAutoPairingAttemptsInProgress(address)) { 632a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 633a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 634a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED && 635a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.getAttempt(address) == 1) { 636a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.addAutoPairingFailure(address); 637a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh pairingAttempt(address, result); 638a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN && 639a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.isAutoPairingAttemptsInProgress(address)) { 640a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh pairingAttempt(address, result); 641a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else { 642a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_NONE, result); 643a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (mBondState.isAutoPairingAttemptsInProgress(address)) { 644a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 645a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 646a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 647a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 648a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 649a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized String getPendingOutgoingBonding() { 650a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return mBondState.getPendingOutgoingBonding(); 651a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 652a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 653a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private void pairingAttempt(String address, int result) { 654a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // This happens when our initial guess of "0000" as the pass key 655a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // fails. Try to create the bond again and display the pin dialog 656a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // to the user. Use back-off while posting the delayed 657a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // message. The initial value is 658a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is 659a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is 660a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // reached, display an error to the user. 661a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh int attempt = mBondState.getAttempt(address); 662a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY > 663a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) { 664a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 665a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_NONE, result); 666a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 667a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 668a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 669a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh Message message = mHandler.obtainMessage(MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); 670a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh message.obj = address; 671a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh boolean postResult = mHandler.sendMessageDelayed(message, 672a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); 673a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (!postResult) { 674a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 675a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, 676a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh BluetoothDevice.BOND_NONE, result); 677a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 678a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6819a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ BluetoothDevice getRemoteDevice(String address) { 6829a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapter.getRemoteDevice(address); 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String toBondStateString(int bondState) { 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (bondState) { 687005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly case BluetoothDevice.BOND_NONE: 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "not bonded"; 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDING: 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonding"; 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDED: 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonded"; 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "??????"; 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setName(String name) { 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == null) { 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 704d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyString("Name", name); 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 707d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh //TODO(): setPropertyString, setPropertyInteger, setPropertyBoolean 708d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Either have a single property function with Object as the parameter 709d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // or have a function for each property and then obfuscate in the JNI layer. 710d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The following looks dirty. 711d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyString(String key, String value) { 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 7138c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 714d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyStringNative(key, value); 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 717d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyInteger(String key, int value) { 718d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 7198c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 720d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyIntegerNative(key, value); 721d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 723d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyBoolean(String key, boolean value) { 724d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 7258c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 726d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyBooleanNative(key, value ? 1 : 0); 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /** 730d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Set the discoverability window for the device. A timeout of zero 731d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * makes the device permanently discoverable (if the device is 732d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * discoverable). Setting the timeout to a nonzero value does not make 733d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * a device discoverable; you need to call setMode() to make the device 734d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * explicitly discoverable. 735d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 736f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby * @param timeout The discoverable timeout in seconds. 737d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh */ 738d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean setDiscoverableTimeout(int timeout) { 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 741d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyInteger("DiscoverableTimeout", timeout); 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 74412835478ee687a493d1b5882e67b6725bd539c26Nick Pelly public synchronized boolean setScanMode(int mode, int duration) { 74518b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, 74618b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly "Need WRITE_SECURE_SETTINGS permission"); 7477f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return setScanMode(mode, duration, true); 7487f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7497f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 7507f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 7517f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * @param on true set the local Bluetooth module to be connectable 7527f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * but not dicoverable 7537f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * false set the local Bluetooth module to be not connectable 7547f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * and not dicoverable 7557f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 7567f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ synchronized void switchConnectable(boolean on) { 7577f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (on) { 7587f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // 0 is a dummy value, does not apply for SCAN_MODE_CONNECTABLE 7597f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, 0, false); 7607f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else { 7617f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // 0 is a dummy value, does not apply for SCAN_MODE_NONE 7627f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setScanMode(BluetoothAdapter.SCAN_MODE_NONE, 0, false); 7637f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7647f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7657f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 7667f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private synchronized boolean setScanMode(int mode, int duration, boolean allowOnlyInOnState) { 7679a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean pairable; 7689a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean discoverable; 76912835478ee687a493d1b5882e67b6725bd539c26Nick Pelly 770de893f550301a60274e87aa8168225e7a7a42184Nick Pelly switch (mode) { 771de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 772d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = false; 773d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 774de893f550301a60274e87aa8168225e7a7a42184Nick Pelly break; 775de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 776d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 777d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 778005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 779de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 780d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 781d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = true; 78212835478ee687a493d1b5882e67b6725bd539c26Nick Pelly if (DBG) Log.d(TAG, "BT Discoverable for " + duration + " seconds"); 783005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 784de893f550301a60274e87aa8168225e7a7a42184Nick Pelly default: 785de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Log.w(TAG, "Requested invalid scan mode " + mode); 786de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return false; 787d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7897f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (allowOnlyInOnState) { 7907f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setPropertyBoolean("Pairable", pairable); 7917f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setPropertyBoolean("Discoverable", discoverable); 7927f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else { 7937f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // allowed to set the property through native layer directly 7947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setAdapterPropertyBooleanNative("Pairable", pairable ? 1 : 0); 7957f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setAdapterPropertyBooleanNative("Discoverable", discoverable ? 1 : 0); 7967f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 797d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return true; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 800b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh /*package*/ synchronized String getProperty(String name) { 801b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh if (!isEnabledInternal()) return null; 8029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapterProperties.getProperty(name); 803b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh } 804b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh 8059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothAdapterProperties getAdapterProperties() { 8069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapterProperties; 8079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDeviceProperties getDeviceProperties() { 8109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties; 8119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean isRemoteDeviceInCache(String address) { 8149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties.isInCache(address); 8159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void setRemoteDeviceProperty(String address, String name, String value) { 8189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties.setProperty(address, name, value); 8199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void updateRemoteDevicePropertiesCache(String address) { 8229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties.updateCache(address); 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 825d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getAddress() { 826d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 827d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Address"); 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 830d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getName() { 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 832d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Name"); 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 83558b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh public synchronized ParcelUuid[] getUuids() { 83658b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 83758b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh String value = getProperty("UUIDs"); 83858b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh if (value == null) return null; 83950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh return convertStringToParcelUuid(value); 84050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 84158b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 84250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private synchronized ParcelUuid[] convertStringToParcelUuid(String value) { 84358b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh String[] uuidStrings = null; 84458b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh // The UUIDs are stored as a "," separated string. 84558b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh uuidStrings = value.split(","); 84658b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; 84758b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 84858b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh for (int i = 0; i < uuidStrings.length; i++) { 84958b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh uuids[i] = ParcelUuid.fromString(uuidStrings[i]); 85058b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh } 85158b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh return uuids; 85258b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh } 85358b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 85458b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 856d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Returns the user-friendly name of a remote device. This value is 857d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * returned from our local cache, which is updated when onPropertyChange 858d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * event is received. 859d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Do not expect to retrieve the updated remote name immediately after 860d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * changing the name on the remote device. 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 862d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Bluetooth address of remote device. 863d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 864d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return The user-friendly name of the specified remote device. 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 866d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getRemoteName(String address) { 867d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 868005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 869d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 870d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 8719a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties.getProperty(address, "Name"); 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the discoverability window for the device. A timeout of zero 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * means that the device is permanently discoverable (if the device is 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the discoverable mode). 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The discoverability window of the device, in seconds. A negative 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value indicates an error. 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getDiscoverableTimeout() { 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 884d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String timeout = getProperty("DiscoverableTimeout"); 885d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (timeout != null) 886d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(timeout); 887d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 888d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return -1; 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getScanMode() { 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 8938c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) 894de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 895d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 896d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean pairable = getProperty("Pairable").equals("true"); 897d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean discoverable = getProperty("Discoverable").equals("true"); 898d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return bluezStringToScanMode (pairable, discoverable); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 901d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean startDiscovery() { 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9048c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 9058c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 906d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return startDiscoveryNative(); 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean cancelDiscovery() { 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9128c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 9138c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 914d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return stopDiscoveryNative(); 915d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 916d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 917d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean isDiscovering() { 918d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 919d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return mIsDiscovering; 920d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 921d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 922d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ void setIsDiscovering(boolean isDiscovering) { 923d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mIsDiscovering = isDiscovering; 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 926cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private boolean isBondingFeasible(String address) { 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9298c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 9308c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 931005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9362092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (mBondState.getPendingOutgoingBonding() != null) { 9379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Ignoring createBond(): another device is bonding"); 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a different device is currently bonding, fail 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check for bond state only if we are not performing auto 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pairing exponential back-off attempts. 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mBondState.isAutoPairingAttemptsInProgress(address) && 945005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.getBondState(address) != BluetoothDevice.BOND_NONE) { 9469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Ignoring createBond(): this device is already bonding or bonded"); 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9503fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (address.equals(mDockAddress)) { 9513fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (!writeDockPin()) { 9529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "Error while writing Pin for the dock"); 9533fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 9543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 9553fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 956cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return true; 957cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 9583fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 959cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean createBond(String address) { 960cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isBondingFeasible(address)) return false; 961cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 962cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!createPairedDeviceNative(address, 60000 /*1 minute*/ )) { 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9662092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mBondState.setPendingOutgoingBonding(address); 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); 9682092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 972cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean createBondOutOfBand(String address, byte[] hash, 973cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer) { 974cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isBondingFeasible(address)) return false; 9753fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 976cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!createPairedDeviceOutOfBandNative(address, 60000 /* 1 minute */)) { 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 980cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh setDeviceOutOfBandData(address, hash, randomizer); 9812092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mBondState.setPendingOutgoingBonding(address); 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); 9832092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 987cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean setDeviceOutOfBandData(String address, byte[] hash, 988cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer) { 989cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 990cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 991cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return false; 992cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 993cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair <byte[], byte[]> value = new Pair<byte[], byte[]>(hash, randomizer); 994cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 995cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (DBG) { 9969a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Setting out of band data for: " + address + ":" + 9979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Arrays.toString(hash) + ":" + Arrays.toString(randomizer)); 998cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 999cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1000cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mDeviceOobData.put(address, value); 1001cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return true; 1002cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1003cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1004cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair<byte[], byte[]> getDeviceOutOfBandData(BluetoothDevice device) { 1005cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return mDeviceOobData.get(device.getAddress()); 1006cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1007cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1008cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1009cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized byte[] readOutOfBandData() { 1010cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1011cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH permission"); 1012cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return null; 1013cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1014cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return readAdapterOutOfBandDataNative(); 1015cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1016cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean cancelBondProcess(String address) { 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 10208c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 10218c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1022005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) { 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1030005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 1032d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh cancelDeviceCreationNative(address); 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean removeBond(String address) { 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 10398c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 10408c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1041005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1044f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 10459b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 1046f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh state.sendMessage(BluetoothDeviceProfileState.UNPAIR); 10479b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 10489b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } else { 10499b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 10509b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 10519b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 10529b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 10539b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public synchronized boolean removeBondInternal(String address) { 1054cc2c06656ceafbcd91ec5b679aa6c9eae0d9982cJaikumar Ganesh // Unset the trusted device state and then unpair 1055cc2c06656ceafbcd91ec5b679aa6c9eae0d9982cJaikumar Ganesh setTrust(address, false); 1056d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return removeDeviceNative(getObjectPathFromAddress(address)); 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized String[] listBonds() { 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.listInState(BluetoothDevice.BOND_BONDED); 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1064a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized String[] listInState(int state) { 1065a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return mBondState.listInState(state); 1066a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1067a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getBondState(String address) { 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1070005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1071b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.getBondState(address.toUpperCase()); 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1076a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean setBondState(String address, int state) { 1077a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return setBondState(address, state, 0); 1078a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1079a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 1080a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean setBondState(String address, int state, int reason) { 1081ae5fbb0b4363a2a399e92e310777d7a955a25370Arek Lichwa mBondState.setBondState(address.toUpperCase(), state, reason); 1082a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return true; 1083a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1084a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 10853fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh public synchronized boolean isBluetoothDock(String address) { 10866e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 10879a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Context.MODE_PRIVATE); 10886e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 10896e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh return sp.contains(SHARED_PREFERENCE_DOCK_ADDRESS + address); 10903fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 10913fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 10929488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh /*package*/ String[] getRemoteDeviceProperties(String address) { 10938c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return null; 10948c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 10959488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh String objectPath = getObjectPathFromAddress(address); 10969488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh return (String [])getDevicePropertiesNative(objectPath); 10979488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 10989488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1100efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Sets the remote device trust state. 1101efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 1102efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * @return boolean to indicate operation success or fail 1103efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1104efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean setTrust(String address, boolean value) { 1105005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1106e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1107e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly "Need BLUETOOTH_ADMIN permission"); 1108efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1109efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1110efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 11118c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11128c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 11139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return setDevicePropertyBooleanNative( 11149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby getObjectPathFromAddress(address), "Trusted", value ? 1 : 0); 1115efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1116efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1117efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1118efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Gets the remote device trust state as boolean. 1119efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Note: this value may be 1120efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * retrieved from cache if we retrieved the data before * 1121efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 11229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @return boolean to indicate trusted or untrusted state 1123efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1124efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean getTrustState(String address) { 1125005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1126efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1127efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1128efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1129efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 11309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = mDeviceProperties.getProperty(address, "Trusted"); 1131efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue if (val == null) { 1132efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1133efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } else { 11349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return val.equals("true"); 1135efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1136efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1137efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1138efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1139d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the remote major, minor classes encoded as a 32-bit 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * integer. 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: this value is retrieved from cache, because we get it during 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * remote-device discovery. 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return 32-bit integer encoding the remote major, minor, and service 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * classes. 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getRemoteClass(String address) { 1149005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1150ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1151ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly return BluetoothClass.ERROR; 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = mDeviceProperties.getProperty(address, "Class"); 1154d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (val == null) 1155d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return BluetoothClass.ERROR; 1156d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else { 1157d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(val); 1158d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1160d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1163dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * Gets the UUIDs supported by the remote device 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1165dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @return array of 128bit ParcelUuids 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1167dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public synchronized ParcelUuid[] getRemoteUuids(String address) { 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1169005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11721caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return getUuidFromCache(address); 11731caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 11741caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 11759a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid[] getUuidFromCache(String address) { 11769a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String value = mDeviceProperties.getProperty(address, "UUIDs"); 1177dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh if (value == null) return null; 1178dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1179dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh String[] uuidStrings = null; 1180d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The UUIDs are stored as a "," separated string. 1181dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuidStrings = value.split(","); 1182dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; 1183dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1184dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh for (int i = 0; i < uuidStrings.length; i++) { 1185dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuids[i] = ParcelUuid.fromString(uuidStrings[i]); 1186dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh } 1187d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return uuids; 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 119016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** 119116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Connect and fetch new UUID's using SDP. 119216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * The UUID's found are broadcast as intents. 119316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Optionally takes a uuid and callback to fetch the RFCOMM channel for the 119416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * a given uuid. 119516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to broadcast UUID intents on success 119616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to handle the failure case for 119716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * callback and broadcast intents. 119816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly */ 119916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public synchronized boolean fetchRemoteUuids(String address, ParcelUuid uuid, 120016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback) { 12011caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 12028c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 12038c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 12041caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (!BluetoothAdapter.checkBluetoothAddress(address)) { 12051caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return false; 12061caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12071caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 120816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = new RemoteService(address, uuid); 120916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null && mUuidCallbackTracker.get(service) != null) { 121016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // An SDP query for this address & uuid is already in progress 121116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Do not add this callback for the uuid 121216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 121316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 121416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 12151caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (mUuidIntentTracker.contains(address)) { 12161caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // An SDP query for this address is already in progress 121716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Add this uuid onto the in-progress SDP query 121816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 121916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 122016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 12211caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return true; 12221caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12231caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 1224421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh // If the device is already created, we will 1225421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh // do the SDP on the callback of createDeviceNative. 1226421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh boolean ret= createDeviceNative(address); 12271caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12281caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker.add(address); 122916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 123016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 123116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 12321caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12331caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT); 12341caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh message.obj = address; 12351caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY); 12361caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return ret; 12371caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12381caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1240d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the rfcomm channel associated with the UUID. 124116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Pulls records from the cache only. 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1243d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Address of the remote device 1244dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @param uuid ParcelUuid of the service attribute 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1246d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return rfcomm channel associated with the service attribute 124710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh * -1 on error 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1249dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public int getRemoteServiceChannel(String address, ParcelUuid uuid) { 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 12518c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 12528c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1253005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1254b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 125610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // Check if we are recovering from a crash. 125710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (mDeviceProperties.isEmpty()) { 12589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (mDeviceProperties.updateCache(address) == null) 125910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 126010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 126110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 126210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address); 126310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (value != null && value.containsKey(uuid)) 126410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return value.get(uuid); 126510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setPin(String address, byte[] pin) { 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 12718c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 12728c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pin == null || pin.length <= 0 || pin.length > 16 || 1274005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly !BluetoothAdapter.checkBluetoothAddress(address)) { 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "setPin(" + address + ") called but no native data available, " + 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " or by bluez.\n"); 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bluez API wants pin as a string 12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pinString; 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pinString = new String(pin, "UTF8"); 12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (UnsupportedEncodingException uee) { 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "UTF8 not supported?!?"); 12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return setPinNative(address, pinString, data.intValue()); 12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1296b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPasskey(String address, int passkey) { 1297b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1298b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 12998c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13008c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1301005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (passkey < 0 || passkey > 999999 || !BluetoothAdapter.checkBluetoothAddress(address)) { 1302b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1303b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar 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 setPasskeyNative(address, passkey, data.intValue()); 1313b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1314b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1315b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPairingConfirmation(String address, boolean confirm) { 1316b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1317b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 13188c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13198c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1320b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1321b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1322b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1323b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1324b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1325b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1326b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1327b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1328b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPairingConfirmationNative(address, confirm, data.intValue()); 1329b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1330b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1331cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean setRemoteOutOfBandData(String address) { 1332cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1333cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 1334cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return false; 1335cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh address = address.toUpperCase(); 1336cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1337cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (data == null) { 1338cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Log.w(TAG, "setRemoteOobData(" + address + ") called but no native data available, " + 1339cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1340cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh " or by bluez.\n"); 1341cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return false; 1342cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1343cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1344cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair<byte[], byte[]> val = mDeviceOobData.get(address); 1345cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] hash, randomizer; 1346cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (val == null) { 1347cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh // TODO: check what should be passed in this case. 1348cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh hash = new byte[16]; 1349cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh randomizer = new byte[16]; 1350cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } else { 1351cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh hash = val.first; 1352cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh randomizer = val.second; 1353cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1354cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return setRemoteOutOfBandDataNative(address, hash, randomizer, data.intValue()); 1355cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1356cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1357b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean cancelPairingUserInput(String address) { 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 13608c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13618c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1362005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1365005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 1366397d8f4f4829a45f4fe7a672cc395466bbc0f442Jaikumar Ganesh BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 1370b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "cancelUserInputNative(" + address + ") called but no native data " + 1371b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "available, ignoring. Maybe the PasskeyAgent Request was already cancelled " + 1372b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "by the remote or by bluez.\n"); 13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1375b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return cancelPairingUserInputNative(address, data.intValue()); 13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13788c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh /*package*/ void updateDeviceServiceChannelCache(String address) { 13799a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "updateDeviceServiceChannelCache(" + address + ")"); 13809a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 138110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // We are storing the rfcomm channel numbers only for the uuids 138210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // we are interested in. 13839a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid[] deviceUuids = getRemoteUuids(address); 138416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 13859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ArrayList<ParcelUuid> applicationUuids = new ArrayList<ParcelUuid>(); 138616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 138716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 138816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (RemoteService service : mUuidCallbackTracker.keySet()) { 138916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 139016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly applicationUuids.add(service.uuid); 139116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 139216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 139316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 139410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 13959a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Map <ParcelUuid, Integer> uuidToChannelMap = new HashMap<ParcelUuid, Integer>(); 139616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 139716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for default uuids 139816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : RFCOMM_UUIDS) { 139910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 14009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = getDeviceServiceChannelForUuid(address, uuid); 14019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuidToChannelMap.put(uuid, channel); 14029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "\tuuid(system): " + uuid + " " + channel); 140310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 140410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 140516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for application requested uuids 140616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : applicationUuids) { 140716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 14089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = getDeviceServiceChannelForUuid(address, uuid); 14099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuidToChannelMap.put(uuid, channel); 14109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "\tuuid(application): " + uuid + " " + channel); 141116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 141216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 141316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 141416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 141516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Make application callbacks 141616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 141716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 141816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 141916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 14209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (uuidToChannelMap.containsKey(service.uuid)) { 14219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = uuidToChannelMap.get(service.uuid); 14229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 14239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Making callback for " + service.uuid + 14249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby " with result " + channel); 142516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 142616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 142716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 142816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(channel); 142916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 143016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 143116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 143216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 143316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 143416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 143516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 143616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 143716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Update cache 14389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceServiceChannelCache.put(address, uuidToChannelMap); 143916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 144010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 144110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 14429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private int getDeviceServiceChannelForUuid(String address, 14439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid uuid) { 14449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return getDeviceServiceChannelNative(getObjectPathFromAddress(address), 14459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuid.toString(), 0x0004); 14469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 14479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 144824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly /** 144924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * b is a handle to a Binder instance, so that this service can be notified 145024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * for Applications that terminate unexpectedly, to clean there service 145124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * records 145224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly */ 145324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid, 145424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int channel, IBinder b) { 14558c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 14568c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 14578c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 145824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (serviceName == null || uuid == null || channel < 1 || 145924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) { 146024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 146124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 146224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) { 146324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Log.w(TAG, "Attempted to register a reserved UUID: " + uuid); 146424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 146524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 146624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle = addRfcommServiceRecordNative(serviceName, 146724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(), 146824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly (short)channel); 14699a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "new handle " + Integer.toHexString(handle)); 147024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (handle == -1) { 147124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 147224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 147324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 147424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int pid = Binder.getCallingPid(); 147524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.put(new Integer(handle), new Integer(pid)); 147624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly try { 1477ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh b.linkToDeath(new Reaper(handle, pid, RFCOMM_RECORD_REAPER), 0); 147824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } catch (RemoteException e) {} 147924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return handle; 148024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 148124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 148224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void removeServiceRecord(int handle) { 148324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 148424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly "Need BLUETOOTH permission"); 148524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly checkAndRemoveRecord(handle, Binder.getCallingPid()); 148624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 148724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 148824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private synchronized void checkAndRemoveRecord(int handle, int pid) { 148924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer handleInt = new Integer(handle); 149024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer owner = mServiceRecordToPid.get(handleInt); 149124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (owner != null && pid == owner.intValue()) { 14929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Removing service record " + 14939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Integer.toHexString(handle) + " for pid " + pid); 149424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.remove(handleInt); 149524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly removeServiceRecordNative(handle); 149624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 149724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 149824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 149924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private class Reaper implements IBinder.DeathRecipient { 1500ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int mPid; 1501ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int mHandle; 1502ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int mType; 1503ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1504ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh Reaper(int handle, int pid, int type) { 1505ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mPid = pid; 1506ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mHandle = handle; 1507ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mType = type; 150824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 1509ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1510ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh Reaper(int pid, int type) { 1511ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mPid = pid; 1512ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mType = type; 1513ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1514ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1515ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh @Override 151624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void binderDied() { 151724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly synchronized (BluetoothService.this) { 1518ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (DBG) Log.d(TAG, "Tracked app " + mPid + " died" + "Type:" + mType); 1519ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (mType == RFCOMM_RECORD_REAPER) { 1520ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh checkAndRemoveRecord(mHandle, mPid); 1521ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } else if (mType == STATE_CHANGE_REAPER) { 1522ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mStateChangeTracker.remove(mPid); 1523ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1524ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1525ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1526ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1527ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1528ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1529ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh @Override 1530ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh public boolean changeApplicationBluetoothState(boolean on, 1531ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh IBluetoothStateChangeCallback callback, IBinder binder) { 1532ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int pid = Binder.getCallingPid(); 1533ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh //mStateChangeTracker is a synchronized map 1534ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (!mStateChangeTracker.containsKey(pid)) { 1535ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (on) { 1536ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mStateChangeTracker.put(pid, callback); 1537ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } else { 1538ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return false; 153924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 1540ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } else if (!on) { 1541ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mStateChangeTracker.remove(pid); 154224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 1543ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1544ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (binder != null) { 1545ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh try { 1546ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh binder.linkToDeath(new Reaper(pid, STATE_CHANGE_REAPER), 0); 1547ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } catch (RemoteException e) { 1548ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return false; 1549ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1550ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1551ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1552ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int type; 1553ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (on) { 1554ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_ON; 1555ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } else { 1556ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_OFF; 1557ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1558ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1559ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mBluetoothState.sendMessage(type, callback); 1560ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return true; 1561ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1562ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1563ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh boolean isApplicationStateChangeTrackerEmpty() { 1564ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return mStateChangeTracker.isEmpty(); 1565ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1566ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1567ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh void clearApplicationStateChangeTracker() { 1568ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mStateChangeTracker.clear(); 1569ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1570ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1571ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh Collection<IBluetoothStateChangeCallback> getApplicationStateChangeCallbacks() { 1572ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return mStateChangeTracker.values(); 1573ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1574ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1575ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int getNumberOfApplicationStateChangeTrackers() { 1576ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return mStateChangeTracker.size(); 157724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 157824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 15826e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (intent == null) return; 15836e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String action = intent.getAction(); 15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver resolver = context.getContentResolver(); 15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Query the airplane mode from Settings.System just to make sure that 15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // some random app is not sending this intent and disabling bluetooth 15897f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (isAirplaneModeOn()) { 15907f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_ON); 15917f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else { 15927f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_OFF); 15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15946e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else if (Intent.ACTION_DOCK_EVENT.equals(action)) { 15956e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 15966e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh Intent.EXTRA_DOCK_STATE_UNDOCKED); 15976e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (DBG) Log.v(TAG, "Received ACTION_DOCK_EVENT with State:" + state); 15986e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) { 15996e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockAddress = null; 16006e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockPin = null; 16016e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else { 16026e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences.Editor editor = 16036e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 16046e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.MODE_PRIVATE).edit(); 16056e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh editor.putBoolean(SHARED_PREFERENCE_DOCK_ADDRESS + mDockAddress, true); 160666fce5068a8a3aeb28aaf713843891b286a75280Brad Fitzpatrick editor.apply(); 16076e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } 16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16126e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private void registerForAirplaneMode(IntentFilter filter) { 161344303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final ContentResolver resolver = mContext.getContentResolver(); 161444303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String airplaneModeRadios = Settings.System.getString(resolver, 16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_RADIOS); 161644303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String toggleableRadios = Settings.System.getString(resolver, 161744303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 161844303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 161944303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneSensitive = airplaneModeRadios == null ? true : 162044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH); 162144303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneToggleable = toggleableRadios == null ? false : 162244303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH); 162344303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsAirplaneSensitive) { 16256e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Returns true if airplane mode is currently on */ 16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean isAirplaneModeOn() { 16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Settings.System.getInt(mContext.getContentResolver(), 16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_ON, 0) == 1; 16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16351caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /* Broadcast the Uuid intent */ 16361caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /*package*/ synchronized void sendUuidIntent(String address) { 16376179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh ParcelUuid[] uuid = getUuidFromCache(address); 16386179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_UUID); 16392d3b98d868cda30535505b2a2fba47aa1c9c052bJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 16406179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid); 16416179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 16429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mUuidIntentTracker.remove(address); 164316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 164416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 164516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ synchronized void makeServiceChannelCallbacks(String address) { 164616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 164716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 164816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 164916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 16509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Cleaning up failed UUID channel lookup: " 16519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + service.address + " " + service.uuid); 165216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 165316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 165416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 165516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(-1); 165616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 165716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 165816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 165916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 166016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 166116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 16621caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 16631caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 16667f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) { 1667105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1668105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1669105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 167024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive); 167144303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey pw.println("mIsAirplaneToggleable = " + mIsAirplaneToggleable); 167224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 167324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local address = " + getAddress()); 167424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local name = " + getName()); 167524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("isDiscovering() = " + isDiscovering()); 1676105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 167796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh mAdapter.getProfileProxy(mContext, 167896a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.HEADSET); 16794ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mAdapter.getProfileProxy(mContext, 16804ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.INPUT_DEVICE); 168174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mAdapter.getProfileProxy(mContext, 168274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.PAN); 1683105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 16849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpKnownDevices(pw); 16859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpAclConnectedDevices(pw); 16869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpHeadsetService(pw); 16874ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh dumpInputDeviceProfile(pw); 168874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh dumpPanProfile(pw); 16899a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpApplicationServiceRecords(pw); 16904ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 16914ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 16929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpHeadsetService(PrintWriter pw) { 1693105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--Headset Service--"); 169496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (mBluetoothHeadset != null) { 1695bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices(); 1696bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh if (deviceList.size() == 0) { 169774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No headsets connected"); 1698bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh } else { 1699bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 17009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\ngetConnectedDevices[0] = " + device); 17019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpHeadsetConnectionState(pw, device); 1702bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh pw.println("getBatteryUsageHint() = " + 1703bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh mBluetoothHeadset.getBatteryUsageHint(device)); 170496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 170596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 17065a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh deviceList.clear(); 17075a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh deviceList = mBluetoothHeadset.getDevicesMatchingConnectionStates(new int[] { 170896a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 170974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("--Connected and Disconnected Headsets"); 1710bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 171196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh pw.println(device); 171296a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (mBluetoothHeadset.isAudioConnected(device)) { 171396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh pw.println("SCO audio connected to device:" + device); 171496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 171596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 1716105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 17174ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); 17184ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 17196c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly 17204ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh private void dumpInputDeviceProfile(PrintWriter pw) { 17214ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("\n--Bluetooth Service- Input Device Profile"); 17224ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (mInputDevice != null) { 17234ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh List<BluetoothDevice> deviceList = mInputDevice.getConnectedDevices(); 17244ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (deviceList.size() == 0) { 172574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No input devices connected"); 17264ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else { 172774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("Number of connected devices:" + deviceList.size()); 17284ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 17294ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectedDevices[0] = " + device); 17304ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("Priority of Connected device = " + mInputDevice.getPriority(device)); 17314ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 17324ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh switch (mInputDevice.getConnectionState(device)) { 17334ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTING: 17344ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTING"); 17354ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 17364ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTED: 17374ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTED"); 17384ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 17394ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_DISCONNECTING: 17404ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_DISCONNECTING"); 17414ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 17424ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 17434ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 17444ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh deviceList.clear(); 17454ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh deviceList = mInputDevice.getDevicesMatchingConnectionStates(new int[] { 17464ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 17474ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("--Connected and Disconnected input devices"); 17484ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 17494ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println(device); 17504ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 175124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 17524ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mAdapter.closeProfileProxy(BluetoothProfile.INPUT_DEVICE, mBluetoothHeadset); 17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 175574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private void dumpPanProfile(PrintWriter pw) { 175674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("\n--Bluetooth Service- Pan Profile"); 175774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (mPan != null) { 175874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh List<BluetoothDevice> deviceList = mPan.getConnectedDevices(); 175974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (deviceList.size() == 0) { 176074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No Pan devices connected"); 176174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else { 176274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("Number of connected devices:" + deviceList.size()); 176374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 176474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectedDevices[0] = " + device); 176574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 176674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh switch (mPan.getConnectionState(device)) { 176774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTING: 176874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTING"); 176974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 177074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTED: 177174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTED"); 177274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 177374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_DISCONNECTING: 177474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_DISCONNECTING"); 177574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 177674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 177774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 177874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh deviceList.clear(); 177974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh deviceList = mPan.getDevicesMatchingConnectionStates(new int[] { 178074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 178174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("--Connected and Disconnected Pan devices"); 178274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 178374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println(device); 178474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 178574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 17869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 17879a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 17889a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpHeadsetConnectionState(PrintWriter pw, 17899a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDevice device) { 17909a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby switch (mBluetoothHeadset.getConnectionState(device)) { 17919a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_CONNECTING: 17929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_CONNECTING"); 17939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 17949a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_CONNECTED: 17959a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_CONNECTED"); 17969a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 17979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_DISCONNECTING: 17989a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_DISCONNECTING"); 17999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 18009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_AUDIO_CONNECTED: 18019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_AUDIO_CONNECTED"); 18029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 18039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 18069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpApplicationServiceRecords(PrintWriter pw) { 18079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--Application Service Records--"); 18089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (Integer handle : mServiceRecordToPid.keySet()) { 18099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Integer pid = mServiceRecordToPid.get(handle); 18109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle)); 18119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 181274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mAdapter.closeProfileProxy(BluetoothProfile.PAN, mBluetoothHeadset); 181374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 181474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 18159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpAclConnectedDevices(PrintWriter pw) { 18169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] devicesObjectPath = getKnownDevices(); 18179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--ACL connected devices--"); 18189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (devicesObjectPath != null) { 18199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String device : devicesObjectPath) { 18209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println(getAddressFromObjectPath(device)); 18219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 18259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpKnownDevices(PrintWriter pw) { 18269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--Known devices--"); 18279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String address : mDeviceProperties.keySet()) { 18289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int bondState = mBondState.getBondState(address); 18299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.printf("%s %10s (%d) %s\n", address, 18309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby toBondStateString(bondState), 18319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mBondState.getAttempt(address), 18329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby getRemoteName(address)); 18339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 18349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Map<ParcelUuid, Integer> uuidChannels = mDeviceServiceChannelCache.get(address); 18359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (uuidChannels == null) { 18369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tuuids = null"); 18379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } else { 18389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (ParcelUuid uuid : uuidChannels.keySet()) { 18399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Integer channel = uuidChannels.get(uuid); 18409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (channel == null) { 18419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\t" + uuid); 18429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } else { 18439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\t" + uuid + " RFCOMM channel = " + channel); 18449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (RemoteService service : mUuidCallbackTracker.keySet()) { 18489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (service.address.equals(address)) { 18499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tPENDING CALLBACK: " + service.uuid); 18509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18549a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 185596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 185696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh new BluetoothProfile.ServiceListener() { 185796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh public void onServiceConnected(int profile, BluetoothProfile proxy) { 18584ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (profile == BluetoothProfile.HEADSET) { 18594ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mBluetoothHeadset = (BluetoothHeadset) proxy; 18604ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else if (profile == BluetoothProfile.INPUT_DEVICE) { 18614ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mInputDevice = (BluetoothInputDevice) proxy; 186274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else if (profile == BluetoothProfile.PAN) { 186374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mPan = (BluetoothPan) proxy; 18644ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 18654ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 186696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh public void onServiceDisconnected(int profile) { 18674ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (profile == BluetoothProfile.HEADSET) { 18684ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mBluetoothHeadset = null; 18694ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else if (profile == BluetoothProfile.INPUT_DEVICE) { 18704ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mInputDevice = null; 187174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else if (profile == BluetoothProfile.PAN) { 187274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mPan = null; 18734ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 187496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 187596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh }; 187696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 1877d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) { 1878d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (pairable && discoverable) 1879bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1880d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else if (pairable && !discoverable) 1881bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 1882d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 1883bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static String scanModeToBluezString(int mode) { 18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mode) { 1888bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "off"; 1890bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "connectable"; 1892bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "discoverable"; 18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1898d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getAddressFromObjectPath(String objectPath) { 18999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String adapterObjectPath = mAdapterProperties.getObjectPath(); 1900d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (adapterObjectPath == null || objectPath == null) { 1901f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath + 1902d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " or deviceObjectPath:" + objectPath + " is null"); 1903d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1904d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1905d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!objectPath.startsWith(adapterObjectPath)) { 1906f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath + 1907d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " is not a prefix of deviceObjectPath:" + objectPath + 1908d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh "bluetoothd crashed ?"); 1909d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1910d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1911d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String address = objectPath.substring(adapterObjectPath.length()); 1912d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (address != null) return address.replace('_', ':'); 1913d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1914d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: Address being returned is null"); 1915d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1916d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1917d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1918d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getObjectPathFromAddress(String address) { 19199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String path = mAdapterProperties.getObjectPath(); 1920d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (path == null) { 1921d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "Error: Object Path is null"); 1922d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1923d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1924d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh path = path + address.replace(":", "_"); 1925d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return path; 1926d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1927d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1928b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh /*package */ void setLinkTimeout(String address, int num_slots) { 1929b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh String path = getObjectPathFromAddress(address); 1930b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh boolean result = setLinkTimeoutNative(path, num_slots); 1931b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 19329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (!result) Log.d(TAG, "Set Link Timeout to " + num_slots + " slots failed"); 1933b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh } 1934b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 193530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /**** Handlers for PAN Profile ****/ 19366003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh // TODO: This needs to be converted to a state machine. 193730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19386003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean isTetheringOn() { 193930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 19406003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19416003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.isTetheringOn(); 19426003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 194330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 194430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19456003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/boolean allowIncomingTethering() { 19466003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19476003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.allowIncomingTethering(); 19486003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 194930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 195030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19516003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public void setBluetoothTethering(boolean value) { 195230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 19536003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19546003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothPanProfileHandler.setBluetoothTethering(value); 19556003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 195630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 195730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19586003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public int getPanDeviceConnectionState(BluetoothDevice device) { 195930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 19606003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19616003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.getPanDeviceConnectionState(device); 19626003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 196330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 196430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19656003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean connectPanDevice(BluetoothDevice device) { 196630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 196730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 19686003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19696003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.connectPanDevice(device); 19706003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 197130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 197230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19736003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getConnectedPanDevices() { 197430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 19756003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19766003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.getConnectedPanDevices(); 19776003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 197830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 197930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19806003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getPanDevicesMatchingConnectionStates( 198174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh int[] states) { 198274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 19836003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19846003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.getPanDevicesMatchingConnectionStates(states); 19856003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 198674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 198774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 19886003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean disconnectPanDevice(BluetoothDevice device) { 198930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 199030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 19916003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 19926003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.disconnectPanDevice(device); 19936003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 199430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 199530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 19966003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/void handlePanDeviceStateChange(BluetoothDevice device, 199730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh String iface, 199830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int state, 199930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int role) { 20006003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 20016003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, iface, state, role); 20026003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 200330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 200430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20056003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/void handlePanDeviceStateChange(BluetoothDevice device, 200630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int state, int role) { 20076003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 20086003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, null, state, role); 20096003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 201030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 201130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 201230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /**** Handlers for Input Device Profile ****/ 20136003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh // This needs to be converted to state machine 201430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20156003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean connectInputDevice(BluetoothDevice device) { 201630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 201730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 201830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress()); 20196003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 20206003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.connectInputDevice(device, state); 20216003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 202230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 202330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20246003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean connectInputDeviceInternal(BluetoothDevice device) { 20256003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 20266003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.connectInputDeviceInternal(device); 20276003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 202830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 202930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20306003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean disconnectInputDevice(BluetoothDevice device) { 203130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 203230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 203330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress()); 20346003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 20356003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.disconnectInputDevice(device, state); 20366003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 203730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 203830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20396003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean disconnectInputDeviceInternal(BluetoothDevice device) { 20406003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 20416003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device); 20426003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 204330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 204430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20456003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public int getInputDeviceConnectionState(BluetoothDevice device) { 204630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 20476003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 20486003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device); 20496003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 205030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 205130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20526003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getConnectedInputDevices() { 205330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 20546003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 20556003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getConnectedInputDevices(); 20566003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 205730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 205830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20596003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getInputDevicesMatchingConnectionStates( 20604ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh int[] states) { 20614ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 20626003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 20636003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states); 20646003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 20654ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 20664ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 20674ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 20686003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public int getInputDevicePriority(BluetoothDevice device) { 206930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 20706003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 20716003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getInputDevicePriority(device); 20726003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 207330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 207430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20756003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean setInputDevicePriority(BluetoothDevice device, int priority) { 207630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 207730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 20786003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 20796003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.setInputDevicePriority(device, priority); 20806003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 208130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 208230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 2083a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie public boolean allowIncomingHidConnect(BluetoothDevice device, boolean allow) { 2084a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 2085a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie "Need BLUETOOTH_ADMIN permission"); 2086a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie String address = device.getAddress(); 2087a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (!BluetoothAdapter.checkBluetoothAddress(address)) { 2088a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return false; 2089a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2090a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2091a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Integer data = getAuthorizationAgentRequestData(address); 2092a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (data == null) { 2093a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Log.w(TAG, "allowIncomingHidConnect(" + device + 2094a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie ") called but no native data available"); 2095a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return false; 2096a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2097a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (DBG) log("allowIncomingHidConnect: " + device + " : " + allow + " : " + data); 2098a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return setAuthorizationNative(address, allow, data.intValue()); 2099a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2100a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 21016003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) { 21026003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 21036003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.lookupInputDevicesMatchingStates(states); 21046003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 210530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 210630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 21076003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/void handleInputDevicePropertyChange(String address, boolean connected) { 21086003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 21096003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothInputProfileHandler.handleInputDevicePropertyChange(address, connected); 21106003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 211130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 211230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 21132ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /**** Handlers for Health Device Profile ****/ 21142ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh // TODO: All these need to be converted to a state machine. 21152ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 2116fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config, 2117fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh IBluetoothHealthCallback callback) { 21182ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 21192ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 21202ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 2121fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh return mBluetoothHealthProfileHandler.registerAppConfiguration(config, callback); 21222ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21232ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21242ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21252ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) { 21262ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 21272ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 21282ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 21292ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.unregisterAppConfiguration(config); 21302ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21312ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21332ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21342ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean connectChannelToSource(BluetoothDevice device, 21352ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config) { 21362ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 21372ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 21382ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 21392ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.connectChannelToSource(device, 21402ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh config); 21412ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21422ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21432ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21442ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean connectChannelToSink(BluetoothDevice device, 21452ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config, int channelType) { 21462ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 21472ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 21482ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 21492ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.connectChannel(device, config, 21502ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh channelType); 21512ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21532ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21542ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean disconnectChannel(BluetoothDevice device, 21552ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) { 21562ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 21572ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 21582ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 21592ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.disconnectChannel(device, config, fd); 21602ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21612ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21622ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21632ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device, 21642ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config) { 21652ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 21662ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 21672ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 21682ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.getMainChannelFd(device, config); 21692ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21702ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21712ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21722ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /*package*/ void onHealthDevicePropertyChanged(String devicePath, 21732ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh String channelPath) { 21742ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 21752ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mBluetoothHealthProfileHandler.onHealthDevicePropertyChanged(devicePath, 21762ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh channelPath); 21772ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21782ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21792ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21802ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /*package*/ void onHealthDeviceChannelChanged(String devicePath, 21812ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh String channelPath, boolean exists) { 21822ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized(mBluetoothHealthProfileHandler) { 21832ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mBluetoothHealthProfileHandler.onHealthDeviceChannelChanged(devicePath, 21842ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh channelPath, exists); 21852ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21862ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21872ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21882ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public int getHealthDeviceConnectionState(BluetoothDevice device) { 21892ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 21902ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 21912ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 21922ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.getHealthDeviceConnectionState(device); 21932ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21942ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 21952ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 21962ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public List<BluetoothDevice> getConnectedHealthDevices() { 21972ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 21982ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 21992ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 22002ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.getConnectedHealthDevices(); 22012ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22022ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22032ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 22042ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public List<BluetoothDevice> getHealthDevicesMatchingConnectionStates( 22052ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh int[] states) { 22062ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 22072ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 22082ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 22092ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler. 22102ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh getHealthDevicesMatchingConnectionStates(states); 22112ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22122ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22132ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 2214a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /*package*/boolean notifyIncomingHidConnection(String address) { 2215a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 2216a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (state == null) { 2217a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return false; 2218a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2219a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Message msg = new Message(); 2220a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie msg.what = BluetoothDeviceProfileState.CONNECT_HID_INCOMING; 2221a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie state.sendMessage(msg); 2222a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return true; 2223a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2224a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 22259b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectHeadset(String address) { 222696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 222796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2228f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 22299b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2230f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2231f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING; 2232f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2233f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.sendMessage(msg); 2234f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh return true; 22359b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22369b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 22379b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22389b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22399b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectHeadset(String address) { 224096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 224196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2242f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 22439b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2244f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2245f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HFP_OUTGOING; 2246f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2247f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.sendMessage(msg); 22489b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 22499b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22509b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 22519b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22529b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22539b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectSink(String address) { 225496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 225596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2256f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 22579b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2258f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2259f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING; 2260f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2261f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.sendMessage(msg); 2262f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh return true; 22639b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22649b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 22659b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22669b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22679b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectSink(String address) { 226896a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 226996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2270f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 22719b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2272f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2273f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_A2DP_OUTGOING; 2274f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2275f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.sendMessage(msg); 22769b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 22779b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22789b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 22799b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22809b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 2281d3728cb32fbd0a85bc77f4bcbdfea386ede2c75fJaikumar Ganesh BluetoothDeviceProfileState addProfileState(String address, boolean setTrust) { 2282f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 22839b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) return state; 22849b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 2285d3728cb32fbd0a85bc77f4bcbdfea386ede2c75fJaikumar Ganesh state = new BluetoothDeviceProfileState(mContext, address, this, mA2dpService, setTrust); 2286f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.put(address, state); 22879b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.start(); 22889b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return state; 22899b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22909b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22919a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void removeProfileState(String address) { 2292f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.remove(address); 22939b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 22949b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 22959a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby synchronized String[] getKnownDevices() { 22969a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = null; 22979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = getProperty("Devices"); 22989a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (val != null) { 22999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby bonds = val.split(","); 23009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 23019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return bonds; 23029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 23039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 23049b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private void initProfileState() { 23059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = null; 23069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = mAdapterProperties.getProperty("Devices"); 23079b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (val != null) { 23089b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh bonds = val.split(","); 23099b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23109b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (bonds == null) { 23119b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return; 23129b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23139b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh for (String path : bonds) { 23149b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh String address = getAddressFromObjectPath(path); 2315d3728cb32fbd0a85bc77f4bcbdfea386ede2c75fJaikumar Ganesh BluetoothDeviceProfileState state = addProfileState(address, false); 23169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 23179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 23189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 23199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void autoConnect() { 23209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = getKnownDevices(); 23219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (bonds == null) { 23229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return; 23239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 23249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String path : bonds) { 23259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String address = getAddressFromObjectPath(path); 23269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 23279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (state != null) { 23289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Message msg = new Message(); 23299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby msg.what = BluetoothDeviceProfileState.AUTO_CONNECT_PROFILES; 23309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state.sendMessage(msg); 23319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 23329b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23339b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23349b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 23359b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean notifyIncomingConnection(String address) { 2336f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = 2337f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.get(address); 23389b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 23399b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 2340f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.what = BluetoothDeviceProfileState.CONNECT_HFP_INCOMING; 23419b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(msg); 23429b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 23439b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23449b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 23459b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23469b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 23479b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /*package*/ boolean notifyIncomingA2dpConnection(String address) { 2348f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = 2349f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.get(address); 23509b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 23519b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 2352f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.what = BluetoothDeviceProfileState.CONNECT_A2DP_INCOMING; 23539b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.sendMessage(msg); 23549b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 23559b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23569b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 23579b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23589b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 23599b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /*package*/ void setA2dpService(BluetoothA2dpService a2dpService) { 23609b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh mA2dpService = a2dpService; 23619b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23629b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 2363a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /*package*/ Integer getAuthorizationAgentRequestData(String address) { 2364a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Integer data = mEventLoop.getAuthorizationAgentRequestData().remove(address); 2365a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return data; 2366a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2367a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 236870a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh public void sendProfileStateMessage(int profile, int cmd) { 236970a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh Message msg = new Message(); 237070a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh msg.what = cmd; 237170a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh if (profile == BluetoothProfileState.HFP) { 237270a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh mHfpProfileState.sendMessage(msg); 237370a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } else if (profile == BluetoothProfileState.A2DP) { 237470a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh mA2dpProfileState.sendMessage(msg); 237570a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } 237670a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } 237770a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh 2378c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh public int getAdapterConnectionState() { 2379c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh return mAdapterConnectionState; 2380c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh } 2381c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 2382a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh public synchronized void sendConnectionStateChange(BluetoothDevice device, int state, 2383a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh int prevState) { 23849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Since this is a binder call check if Bluetooth is on still 23857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return; 23869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 23879a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (updateCountersAndCheckForConnectionStateChange(state, prevState)) { 23889a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (!validateProfileConnectionState(state) || 23899a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby !validateProfileConnectionState(prevState)) { 23909a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Previously, an invalid state was broadcast anyway, 23919a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // with the invalid state converted to -1 in the intent. 23929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Better to log an error and not send an intent with 23939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // invalid contents or set mAdapterConnectionState to -1. 23949a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "Error in sendConnectionStateChange: " 23959a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + "prevState " + prevState + " state " + state); 23969a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return; 23979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 2398c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 2399c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh mAdapterConnectionState = state; 2400c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 24017f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (state == BluetoothProfile.STATE_DISCONNECTED) { 24027f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.ALL_DEVICES_DISCONNECTED); 24037f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 24047f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 2405a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 2406a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 24079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 24089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby convertToAdapterState(state)); 24099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, 24109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby convertToAdapterState(prevState)); 241160b4d2a2bd232a7116fd037501cac704f328c0a1Jaikumar Ganesh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2412a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 24139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "CONNECTION_STATE_CHANGE: " + device + ": " 24149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + prevState + " -> " + state); 2415a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2416a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2417a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 24189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private boolean validateProfileConnectionState(int state) { 24199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (state == BluetoothProfile.STATE_DISCONNECTED || 24209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_CONNECTING || 24219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_CONNECTED || 24229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_DISCONNECTING); 24239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 24249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 24259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private int convertToAdapterState(int state) { 2426a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh switch (state) { 24279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_DISCONNECTED: 24289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_DISCONNECTED; 24299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_DISCONNECTING: 24309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_DISCONNECTING; 24319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_CONNECTED: 24329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_CONNECTED; 2433a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTING: 2434a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh return BluetoothAdapter.STATE_CONNECTING; 24359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 24369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "Error in convertToAdapterState"); 24379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return -1; 24389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 24399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 24409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) { 24419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby switch (prevState) { 24429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_CONNECTING: 24439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesConnecting--; 24449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 24459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 2446a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTED: 24479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesConnected--; 24489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 24499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 2450a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTING: 24519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesDisconnecting--; 24529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 2453a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2454a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2455a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh switch (state) { 2456a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTING: 2457a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnecting++; 24589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesConnecting == 1); 2459a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2460a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTED: 2461a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnected++; 24629a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 1); 2463a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2464a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTING: 2465a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesDisconnecting++; 24669a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesDisconnecting == 1); 2467a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2468a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTED: 24699a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesConnecting == 0); 2470a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 24719a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby default: 24729a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return true; 2473a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 24749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2475d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2476a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private void createIncomingConnectionStateFile() { 2477a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie File f = new File(INCOMING_CONNECTION_FILE); 2478a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (!f.exists()) { 2479a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2480a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie f.createNewFile(); 2481a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2482a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Log.e(TAG, "IOException: cannot create file"); 2483a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2484a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2485a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2486a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2487a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /** @hide */ 2488a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie public Pair<Integer, String> getIncomingState(String address) { 2489a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (mIncomingConnections.isEmpty()) { 2490a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie createIncomingConnectionStateFile(); 2491a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie readIncomingConnectionState(); 2492a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2493a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return mIncomingConnections.get(address); 2494a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2495a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2496a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private void readIncomingConnectionState() { 2497a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie synchronized(mIncomingConnections) { 2498a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie FileInputStream fstream = null; 2499a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2500a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie fstream = new FileInputStream(INCOMING_CONNECTION_FILE); 2501a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie DataInputStream in = new DataInputStream(fstream); 2502a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie BufferedReader file = new BufferedReader(new InputStreamReader(in)); 2503a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie String line; 2504a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie while((line = file.readLine()) != null) { 2505a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie line = line.trim(); 2506a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (line.length() == 0) continue; 2507a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie String[] value = line.split(","); 2508a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (value != null && value.length == 3) { 2509a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Integer val1 = Integer.parseInt(value[1]); 2510a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Pair<Integer, String> val = new Pair(val1, value[2]); 2511a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mIncomingConnections.put(value[0], val); 2512a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2513a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2514a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (FileNotFoundException e) { 2515a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("FileNotFoundException: readIncomingConnectionState" + e.toString()); 2516a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2517a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("IOException: readIncomingConnectionState" + e.toString()); 2518a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } finally { 2519a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (fstream != null) { 2520a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2521a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie fstream.close(); 2522a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2523a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie // Ignore 2524a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2525a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2526a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2527a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2528a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2529a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2530a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private void truncateIncomingConnectionFile() { 2531a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie RandomAccessFile r = null; 2532a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2533a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie r = new RandomAccessFile(INCOMING_CONNECTION_FILE, "rw"); 2534a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie r.setLength(0); 2535a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (FileNotFoundException e) { 2536a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("FileNotFoundException: truncateIncomingConnectionState" + e.toString()); 2537a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2538a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("IOException: truncateIncomingConnectionState" + e.toString()); 2539a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } finally { 2540a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (r != null) { 2541a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2542a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie r.close(); 2543a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2544a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie // ignore 2545a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2546a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2547a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2548a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2549a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2550a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /** @hide */ 2551a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie public void writeIncomingConnectionState(String address, Pair<Integer, String> data) { 2552a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie synchronized(mIncomingConnections) { 2553a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mIncomingConnections.put(address, data); 2554a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2555a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie truncateIncomingConnectionFile(); 2556a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie BufferedWriter out = null; 2557a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie StringBuilder value = new StringBuilder(); 2558a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2559a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie out = new BufferedWriter(new FileWriter(INCOMING_CONNECTION_FILE, true)); 2560a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie for (String devAddress: mIncomingConnections.keySet()) { 2561a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Pair<Integer, String> val = mIncomingConnections.get(devAddress); 2562a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(devAddress); 2563a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(","); 2564a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(val.first.toString()); 2565a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(","); 2566a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(val.second); 2567a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append("\n"); 2568a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2569a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie out.write(value.toString()); 2570a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (FileNotFoundException e) { 2571a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("FileNotFoundException: writeIncomingConnectionState" + e.toString()); 2572a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2573a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("IOException: writeIncomingConnectionState" + e.toString()); 2574a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } finally { 2575a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (out != null) { 2576a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2577a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie out.close(); 2578a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2579a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie // Ignore 2580a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2581a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2582a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2583a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2584a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2585a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2586a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private static void log(String msg) { 2587a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Log.d(TAG, msg); 2588a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2589a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2590d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native static void classInitNative(); 2591d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void initializeNativeDataNative(); 2592d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setupNativeDataNative(); 2593d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean tearDownNativeDataNative(); 2594d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void cleanupNativeDataNative(); 25959a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ native String getAdapterPathNative(); 2596d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2597d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int isEnabledNative(); 25987f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ native int enableNative(); 25997f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ native int disableNative(); 2600d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 26019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ native Object[] getAdapterPropertiesNative(); 2602d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native Object[] getDevicePropertiesNative(String objectPath); 2603d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyStringNative(String key, String value); 2604d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyIntegerNative(String key, int value); 2605d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyBooleanNative(String key, int value); 2606d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2607d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean startDiscoveryNative(); 2608d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean stopDiscoveryNative(); 2609d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2610d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean createPairedDeviceNative(String address, int timeout_ms); 2611cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native boolean createPairedDeviceOutOfBandNative(String address, int timeout_ms); 2612cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native byte[] readAdapterOutOfBandDataNative(); 2613cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 2614d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean cancelDeviceCreationNative(String address); 2615d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean removeDeviceNative(String objectPath); 2616d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int getDeviceServiceChannelNative(String objectPath, String uuid, 2617d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh int attributeId); 2618d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2619b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean cancelPairingUserInputNative(String address, int nativeData); 2620d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setPinNative(String address, String pin, int nativeData); 2621b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPasskeyNative(String address, int passkey, int nativeData); 2622b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPairingConfirmationNative(String address, boolean confirm, 2623b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh int nativeData); 2624cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native boolean setRemoteOutOfBandDataNative(String address, byte[] hash, 2625cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer, int nativeData); 2626cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 262724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean setDevicePropertyBooleanNative(String objectPath, String key, 262824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int value); 26291caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private native boolean createDeviceNative(String address); 263016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ native boolean discoverServicesNative(String objectPath, String pattern); 263110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 263224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb, 263324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly short channel); 263424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean removeServiceRecordNative(int handle); 2635b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh private native boolean setLinkTimeoutNative(String path, int num_slots); 2636a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 263730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh native boolean connectInputDeviceNative(String path); 263830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh native boolean disconnectInputDeviceNative(String path); 26396fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 2640a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge); 2641a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean connectPanDeviceNative(String path, String dstRole); 2642a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean disconnectPanDeviceNative(String path); 2643a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean disconnectPanServerDeviceNative(String path, 2644a44a1e77ef435942b2ff60e9e60d3a64b43d775bJaikumar Ganesh String address, String iface); 264584690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh 264684690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private native int[] addReservedServiceRecordsNative(int[] uuuids); 264784690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private native boolean removeReservedServiceRecordsNative(int[] handles); 26482ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 26492ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh // Health API 26502ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String registerHealthApplicationNative(int dataType, String role, String name, 26512ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh String channelType); 26522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String registerHealthApplicationNative(int dataType, String role, String name); 26532ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native boolean unregisterHealthApplicationNative(String path); 26542ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native boolean createChannelNative(String devicePath, String appPath, String channelType); 26552ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native boolean destroyChannelNative(String devicePath, String channelpath); 26562ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String getMainChannelNative(String path); 26572ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String getChannelApplicationNative(String channelPath); 26582ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native ParcelFileDescriptor getChannelFdNative(String channelPath); 26592ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native boolean releaseChannelFdNative(String channelPath); 2660a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie native boolean setAuthorizationNative(String address, boolean value, int data); 26619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2662