BluetoothDevice.java revision 228b2f3a813e93413a0f9e2f29dfbfc54590a356
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.bluetooth; 18 19import android.os.RemoteException; 20import android.util.Log; 21 22import java.io.UnsupportedEncodingException; 23 24/** 25 * The Android Bluetooth API is not finalized, and *will* change. Use at your 26 * own risk. 27 * 28 * Manages the local Bluetooth device. Scan for devices, create bondings, 29 * power up and down the adapter. 30 * 31 * @hide 32 */ 33public class BluetoothDevice { 34 35 public static final int BLUETOOTH_STATE_OFF = 0; 36 public static final int BLUETOOTH_STATE_TURNING_ON = 1; 37 public static final int BLUETOOTH_STATE_ON = 2; 38 public static final int BLUETOOTH_STATE_TURNING_OFF = 3; 39 40 /** Inquiry scan and page scan are both off. 41 * Device is neither discoverable nor connectable */ 42 public static final int SCAN_MODE_NONE = 0; 43 /** Page scan is on, inquiry scan is off. 44 * Device is connectable, but not discoverable */ 45 public static final int SCAN_MODE_CONNECTABLE = 1; 46 /** Page scan and inquiry scan are on. 47 * Device is connectable and discoverable */ 48 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 3; 49 50 public static final int RESULT_FAILURE = -1; 51 public static final int RESULT_SUCCESS = 0; 52 53 /** We do not have a link key for the remote device, and are therefore not 54 * bonded */ 55 public static final int BOND_NOT_BONDED = 0; 56 /** We have a link key for the remote device, and are probably bonded. */ 57 public static final int BOND_BONDED = 1; 58 /** We are currently attempting bonding */ 59 public static final int BOND_BONDING = 2; 60 61 //TODO: Unify these result codes in BluetoothResult or BluetoothError 62 /** A bond attempt failed because pins did not match, or remote device did 63 * not respond to pin request in time */ 64 public static final int UNBOND_REASON_AUTH_FAILED = 1; 65 /** A bond attempt failed because the other side explicilty rejected 66 * bonding */ 67 public static final int UNBOND_REASON_AUTH_REJECTED = 2; 68 /** A bond attempt failed because we canceled the bonding process */ 69 public static final int UNBOND_REASON_AUTH_CANCELED = 3; 70 /** A bond attempt failed because we could not contact the remote device */ 71 public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4; 72 /** A bond attempt failed because a discovery is in progress */ 73 public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5; 74 /** An existing bond was explicitly revoked */ 75 public static final int UNBOND_REASON_REMOVED = 6; 76 77 /* The user will be prompted to enter a pin */ 78 public static final int PAIRING_VARIANT_PIN = 0; 79 /* The user will be prompted to enter a passkey */ 80 public static final int PAIRING_VARIANT_PASSKEY = 1; 81 /* The user will be prompted to confirm the passkey displayed on the screen */ 82 public static final int PAIRING_VARIANT_CONFIRMATION = 2; 83 84 85 private static final String TAG = "BluetoothDevice"; 86 87 private final IBluetoothDevice mService; 88 /** 89 * @hide - hide this because it takes a parameter of type 90 * IBluetoothDevice, which is a System private class. 91 * Also note that Context.getSystemService is a factory that 92 * returns a BlueToothDevice. That is the right way to get 93 * a BluetoothDevice. 94 */ 95 public BluetoothDevice(IBluetoothDevice service) { 96 mService = service; 97 } 98 99 /** 100 * Is Bluetooth currently turned on. 101 * 102 * @return true if Bluetooth enabled, false otherwise. 103 */ 104 public boolean isEnabled() { 105 try { 106 return mService.isEnabled(); 107 } catch (RemoteException e) {Log.e(TAG, "", e);} 108 return false; 109 } 110 111 /** 112 * Get the current state of Bluetooth. 113 * 114 * @return One of BLUETOOTH_STATE_ or BluetoothError.ERROR. 115 */ 116 public int getBluetoothState() { 117 try { 118 return mService.getBluetoothState(); 119 } catch (RemoteException e) {Log.e(TAG, "", e);} 120 return BluetoothError.ERROR; 121 } 122 123 /** 124 * Enable the Bluetooth device. 125 * Turn on the underlying hardware. 126 * This is an asynchronous call, 127 * BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION can be used to check if 128 * and when the device is sucessfully enabled. 129 * @return false if we cannot enable the Bluetooth device. True does not 130 * imply the device was enabled, it only implies that so far there were no 131 * problems. 132 */ 133 public boolean enable() { 134 try { 135 return mService.enable(); 136 } catch (RemoteException e) {Log.e(TAG, "", e);} 137 return false; 138 } 139 140 /** 141 * Disable the Bluetooth device. 142 * This turns off the underlying hardware. 143 * 144 * @return true if successful, false otherwise. 145 */ 146 public boolean disable() { 147 try { 148 return mService.disable(true); 149 } catch (RemoteException e) {Log.e(TAG, "", e);} 150 return false; 151 } 152 153 public String getAddress() { 154 try { 155 return mService.getAddress(); 156 } catch (RemoteException e) {Log.e(TAG, "", e);} 157 return null; 158 } 159 160 /** 161 * Get the friendly Bluetooth name of this device. 162 * 163 * This name is visible to remote Bluetooth devices. Currently it is only 164 * possible to retrieve the Bluetooth name when Bluetooth is enabled. 165 * 166 * @return the Bluetooth name, or null if there was a problem. 167 */ 168 public String getName() { 169 try { 170 return mService.getName(); 171 } catch (RemoteException e) {Log.e(TAG, "", e);} 172 return null; 173 } 174 175 /** 176 * Set the friendly Bluetooth name of this device. 177 * 178 * This name is visible to remote Bluetooth devices. The Bluetooth Service 179 * is responsible for persisting this name. 180 * 181 * @param name the name to set 182 * @return true, if the name was successfully set. False otherwise. 183 */ 184 public boolean setName(String name) { 185 try { 186 return mService.setName(name); 187 } catch (RemoteException e) {Log.e(TAG, "", e);} 188 return false; 189 } 190 191 /** 192 * Get the current scan mode. 193 * Used to determine if the local device is connectable and/or discoverable 194 * @return Scan mode, one of SCAN_MODE_* or an error code 195 */ 196 public int getScanMode() { 197 try { 198 return mService.getScanMode(); 199 } catch (RemoteException e) {Log.e(TAG, "", e);} 200 return BluetoothError.ERROR_IPC; 201 } 202 203 /** 204 * Set the current scan mode. 205 * Used to make the local device connectable and/or discoverable 206 * @param scanMode One of SCAN_MODE_* 207 */ 208 public void setScanMode(int scanMode) { 209 try { 210 mService.setScanMode(scanMode); 211 } catch (RemoteException e) {Log.e(TAG, "", e);} 212 } 213 214 public int getDiscoverableTimeout() { 215 try { 216 return mService.getDiscoverableTimeout(); 217 } catch (RemoteException e) {Log.e(TAG, "", e);} 218 return -1; 219 } 220 public void setDiscoverableTimeout(int timeout) { 221 try { 222 mService.setDiscoverableTimeout(timeout); 223 } catch (RemoteException e) {Log.e(TAG, "", e);} 224 } 225 226 public boolean startDiscovery() { 227 try { 228 return mService.startDiscovery(); 229 } catch (RemoteException e) {Log.e(TAG, "", e);} 230 return false; 231 } 232 233 public void cancelDiscovery() { 234 try { 235 mService.cancelDiscovery(); 236 } catch (RemoteException e) {Log.e(TAG, "", e);} 237 } 238 239 public boolean isDiscovering() { 240 try { 241 return mService.isDiscovering(); 242 } catch (RemoteException e) {Log.e(TAG, "", e);} 243 return false; 244 } 245 246 /** 247 * Removes the remote device and the pairing information associated 248 * with it. 249 * 250 * @param address the Bluetooth hardware address you want to disconnect. 251 * @return true if the device was disconnected, false otherwise and on 252 * error. 253 */ 254 public boolean removeBond(String address) { 255 try { 256 return mService.removeBond(address); 257 } catch (RemoteException e) {Log.e(TAG, "", e);} 258 return false; 259 } 260 261 /** 262 * Create a bonding with a remote bluetooth device. 263 * 264 * This is an asynchronous call. The result of this bonding attempt can be 265 * observed through BluetoothIntent.BOND_STATE_CHANGED_ACTION intents. 266 * 267 * @param address the remote device Bluetooth address. 268 * @return false If there was an immediate problem creating the bonding, 269 * true otherwise. 270 */ 271 public boolean createBond(String address) { 272 try { 273 return mService.createBond(address); 274 } catch (RemoteException e) {Log.e(TAG, "", e);} 275 return false; 276 } 277 278 /** 279 * Cancel an in-progress bonding request started with createBond. 280 */ 281 public boolean cancelBondProcess(String address) { 282 try { 283 return mService.cancelBondProcess(address); 284 } catch (RemoteException e) {Log.e(TAG, "", e);} 285 return false; 286 } 287 288 /** 289 * List remote devices that are bonded (paired) to the local device. 290 * 291 * Bonding (pairing) is the process by which the user enters a pin code for 292 * the device, which generates a shared link key, allowing for 293 * authentication and encryption of future connections. In Android we 294 * require bonding before RFCOMM or SCO connections can be made to a remote 295 * device. 296 * 297 * This function lists which remote devices we have a link key for. It does 298 * not cause any RF transmission, and does not check if the remote device 299 * still has it's link key with us. If the other side no longer has its 300 * link key then the RFCOMM or SCO connection attempt will result in an 301 * error. 302 * 303 * This function does not check if the remote device is in range. 304 * 305 * Remote devices that have an in-progress bonding attempt are not 306 * returned. 307 * 308 * @return bluetooth hardware addresses of remote devices that are 309 * bonded. Array size is 0 if no devices are bonded. Null on error. 310 */ 311 public String[] listBonds() { 312 try { 313 return mService.listBonds(); 314 } catch (RemoteException e) {Log.e(TAG, "", e);} 315 return null; 316 } 317 318 /** 319 * Get the bonding state of a remote device. 320 * 321 * Result is one of: 322 * BluetoothError.* 323 * BOND_* 324 * 325 * @param address Bluetooth hardware address of the remote device to check. 326 * @return Result code 327 */ 328 public int getBondState(String address) { 329 try { 330 return mService.getBondState(address); 331 } catch (RemoteException e) {Log.e(TAG, "", e);} 332 return BluetoothError.ERROR_IPC; 333 } 334 335 public String getRemoteName(String address) { 336 try { 337 return mService.getRemoteName(address); 338 } catch (RemoteException e) {Log.e(TAG, "", e);} 339 return null; 340 } 341 342 public int getRemoteClass(String address) { 343 try { 344 return mService.getRemoteClass(address); 345 } catch (RemoteException e) {Log.e(TAG, "", e);} 346 return BluetoothError.ERROR_IPC; 347 } 348 349 public String[] getRemoteUuids(String address) { 350 try { 351 return mService.getRemoteUuids(address); 352 } catch (RemoteException e) {Log.e(TAG, "", e);} 353 return null; 354 } 355 356 public int getRemoteServiceChannel(String address, String uuid) { 357 try { 358 return mService.getRemoteServiceChannel(address, uuid); 359 } catch (RemoteException e) {Log.e(TAG, "", e);} 360 return BluetoothError.ERROR_IPC; 361 } 362 363 public boolean setPin(String address, byte[] pin) { 364 try { 365 return mService.setPin(address, pin); 366 } catch (RemoteException e) {Log.e(TAG, "", e);} 367 return false; 368 } 369 370 public boolean setPasskey(String address, int passkey) { 371 try { 372 return mService.setPasskey(address, passkey); 373 } catch (RemoteException e) {Log.e(TAG, "", e);} 374 return false; 375 } 376 377 public boolean setPairingConfirmation(String address, boolean confirm) { 378 try { 379 return mService.setPairingConfirmation(address, confirm); 380 } catch (RemoteException e) {Log.e(TAG, "", e);} 381 return false; 382 } 383 384 public boolean cancelPairingUserInput(String address) { 385 try { 386 return mService.cancelPairingUserInput(address); 387 } catch (RemoteException e) {Log.e(TAG, "", e);} 388 return false; 389 } 390 391 /** 392 * Check that a pin is valid and convert to byte array. 393 * 394 * Bluetooth pin's are 1 to 16 bytes of UTF8 characters. 395 * @param pin pin as java String 396 * @return the pin code as a UTF8 byte array, or null if it is an invalid 397 * Bluetooth pin. 398 */ 399 public static byte[] convertPinToBytes(String pin) { 400 if (pin == null) { 401 return null; 402 } 403 byte[] pinBytes; 404 try { 405 pinBytes = pin.getBytes("UTF8"); 406 } catch (UnsupportedEncodingException uee) { 407 Log.e(TAG, "UTF8 not supported?!?"); // this should not happen 408 return null; 409 } 410 if (pinBytes.length <= 0 || pinBytes.length > 16) { 411 return null; 412 } 413 return pinBytes; 414 } 415 416 private static final int ADDRESS_LENGTH = 17; 417 /** Sanity check a bluetooth address, such as "00:43:A8:23:10:F0" */ 418 public static boolean checkBluetoothAddress(String address) { 419 if (address == null || address.length() != ADDRESS_LENGTH) { 420 return false; 421 } 422 for (int i = 0; i < ADDRESS_LENGTH; i++) { 423 char c = address.charAt(i); 424 switch (i % 3) { 425 case 0: 426 case 1: 427 if (Character.digit(c, 16) != -1) { 428 break; // hex character, OK 429 } 430 return false; 431 case 2: 432 if (c == ':') { 433 break; // OK 434 } 435 return false; 436 } 437 } 438 return true; 439 } 440} 441