BluetoothAdapter.java revision cf44059813539bf7f36dabd278cef93ba3122c56
1/* 2 * Copyright (C) 2009 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.IOException; 23import java.util.Collections; 24import java.util.Set; 25import java.util.HashSet; 26 27/** 28 * Represents the local Bluetooth adapter. 29 * 30 * <p>Use {@link android.content.Context#getSystemService} with {@link 31 * android.content.Context#BLUETOOTH_SERVICE} to get the default local 32 * Bluetooth adapter. On most Android devices there is only one local 33 * Bluetotoh adapter. 34 * 35 * <p>Use the {@link BluetoothDevice} class for operations on remote Bluetooth 36 * devices. 37 * 38 * <p>TODO: unhide more of this class 39 */ 40public final class BluetoothAdapter { 41 private static final String TAG = "BluetoothAdapter"; 42 43 /** @hide */ 44 public static final int BLUETOOTH_STATE_OFF = 0; 45 /** @hide */ 46 public static final int BLUETOOTH_STATE_TURNING_ON = 1; 47 /** @hide */ 48 public static final int BLUETOOTH_STATE_ON = 2; 49 /** @hide */ 50 public static final int BLUETOOTH_STATE_TURNING_OFF = 3; 51 52 /** Inquiry scan and page scan are both off. 53 * Device is neither discoverable nor connectable 54 * @hide */ 55 public static final int SCAN_MODE_NONE = 0; 56 /** Page scan is on, inquiry scan is off. 57 * Device is connectable, but not discoverable 58 * @hide*/ 59 public static final int SCAN_MODE_CONNECTABLE = 1; 60 /** Page scan and inquiry scan are on. 61 * Device is connectable and discoverable 62 * @hide*/ 63 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 3; 64 65 /** @hide */ 66 public static final int RESULT_FAILURE = -1; 67 /** @hide */ 68 public static final int RESULT_SUCCESS = 0; 69 70 /** The user will be prompted to enter a pin 71 * @hide */ 72 public static final int PAIRING_VARIANT_PIN = 0; 73 /** The user will be prompted to enter a passkey 74 * @hide */ 75 public static final int PAIRING_VARIANT_PASSKEY = 1; 76 /** The user will be prompted to confirm the passkey displayed on the screen 77 * @hide */ 78 public static final int PAIRING_VARIANT_CONFIRMATION = 2; 79 80 private final IBluetooth mService; 81 82 /** 83 * Do not use this constructor. Use Context.getSystemService() instead. 84 * @hide 85 */ 86 public BluetoothAdapter(IBluetooth service) { 87 if (service == null) { 88 throw new IllegalArgumentException("service is null"); 89 } 90 mService = service; 91 } 92 93 /** 94 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware 95 * address. 96 * <p>Valid Bluetooth hardware addresses must be upper case, in a format 97 * such as "00:11:22:33:AA:BB". 98 * <p>A {@link BluetoothDevice} will always be returned for a valid 99 * hardware address, even if this adapter has never seen that device. 100 * @param address valid Bluetooth MAC address 101 * @throws IllegalArgumentException if address is invalid 102 */ 103 public BluetoothDevice getRemoteDevice(String address) { 104 return new BluetoothDevice(address); 105 } 106 107 /** 108 * Is Bluetooth currently turned on. 109 * 110 * @return true if Bluetooth enabled, false otherwise. 111 * @hide 112 */ 113 public boolean isEnabled() { 114 try { 115 return mService.isEnabled(); 116 } catch (RemoteException e) {Log.e(TAG, "", e);} 117 return false; 118 } 119 120 /** 121 * Get the current state of Bluetooth. 122 * 123 * @return One of BLUETOOTH_STATE_ or BluetoothError.ERROR. 124 * @hide 125 */ 126 public int getBluetoothState() { 127 try { 128 return mService.getBluetoothState(); 129 } catch (RemoteException e) {Log.e(TAG, "", e);} 130 return BluetoothError.ERROR; 131 } 132 133 /** 134 * Enable the Bluetooth device. 135 * Turn on the underlying hardware. 136 * This is an asynchronous call, 137 * BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION can be used to check if 138 * and when the device is sucessfully enabled. 139 * @return false if we cannot enable the Bluetooth device. True does not 140 * imply the device was enabled, it only implies that so far there were no 141 * problems. 142 * @hide 143 */ 144 public boolean enable() { 145 try { 146 return mService.enable(); 147 } catch (RemoteException e) {Log.e(TAG, "", e);} 148 return false; 149 } 150 151 /** 152 * Disable the Bluetooth device. 153 * This turns off the underlying hardware. 154 * 155 * @return true if successful, false otherwise. 156 * @hide 157 */ 158 public boolean disable() { 159 try { 160 return mService.disable(true); 161 } catch (RemoteException e) {Log.e(TAG, "", e);} 162 return false; 163 } 164 165 /** @hide */ 166 public String getAddress() { 167 try { 168 return mService.getAddress(); 169 } catch (RemoteException e) {Log.e(TAG, "", e);} 170 return null; 171 } 172 173 /** 174 * Get the friendly Bluetooth name of this device. 175 * 176 * This name is visible to remote Bluetooth devices. Currently it is only 177 * possible to retrieve the Bluetooth name when Bluetooth is enabled. 178 * 179 * @return the Bluetooth name, or null if there was a problem. 180 * @hide 181 */ 182 public String getName() { 183 try { 184 return mService.getName(); 185 } catch (RemoteException e) {Log.e(TAG, "", e);} 186 return null; 187 } 188 189 /** 190 * Set the friendly Bluetooth name of this device. 191 * 192 * This name is visible to remote Bluetooth devices. The Bluetooth Service 193 * is responsible for persisting this name. 194 * 195 * @param name the name to set 196 * @return true, if the name was successfully set. False otherwise. 197 * @hide 198 */ 199 public boolean setName(String name) { 200 try { 201 return mService.setName(name); 202 } catch (RemoteException e) {Log.e(TAG, "", e);} 203 return false; 204 } 205 206 /** 207 * Get the current scan mode. 208 * Used to determine if the local device is connectable and/or discoverable 209 * @return Scan mode, one of SCAN_MODE_* or an error code 210 * @hide 211 */ 212 public int getScanMode() { 213 try { 214 return mService.getScanMode(); 215 } catch (RemoteException e) {Log.e(TAG, "", e);} 216 return BluetoothError.ERROR_IPC; 217 } 218 219 /** 220 * Set the current scan mode. 221 * Used to make the local device connectable and/or discoverable 222 * @param scanMode One of SCAN_MODE_* 223 * @hide 224 */ 225 public void setScanMode(int scanMode) { 226 try { 227 mService.setScanMode(scanMode); 228 } catch (RemoteException e) {Log.e(TAG, "", e);} 229 } 230 231 /** @hide */ 232 public int getDiscoverableTimeout() { 233 try { 234 return mService.getDiscoverableTimeout(); 235 } catch (RemoteException e) {Log.e(TAG, "", e);} 236 return -1; 237 } 238 239 /** @hide */ 240 public void setDiscoverableTimeout(int timeout) { 241 try { 242 mService.setDiscoverableTimeout(timeout); 243 } catch (RemoteException e) {Log.e(TAG, "", e);} 244 } 245 246 /** @hide */ 247 public boolean startDiscovery() { 248 try { 249 return mService.startDiscovery(); 250 } catch (RemoteException e) {Log.e(TAG, "", e);} 251 return false; 252 } 253 254 /** @hide */ 255 public void cancelDiscovery() { 256 try { 257 mService.cancelDiscovery(); 258 } catch (RemoteException e) {Log.e(TAG, "", e);} 259 } 260 261 /** @hide */ 262 public boolean isDiscovering() { 263 try { 264 return mService.isDiscovering(); 265 } catch (RemoteException e) {Log.e(TAG, "", e);} 266 return false; 267 } 268 269 /** 270 * List remote devices that are bonded (paired) to the local adapter. 271 * 272 * Bonding (pairing) is the process by which the user enters a pin code for 273 * the device, which generates a shared link key, allowing for 274 * authentication and encryption of future connections. In Android we 275 * require bonding before RFCOMM or SCO connections can be made to a remote 276 * device. 277 * 278 * This function lists which remote devices we have a link key for. It does 279 * not cause any RF transmission, and does not check if the remote device 280 * still has it's link key with us. If the other side no longer has its 281 * link key then the RFCOMM or SCO connection attempt will result in an 282 * error. 283 * 284 * This function does not check if the remote device is in range. 285 * 286 * Remote devices that have an in-progress bonding attempt are not 287 * returned. 288 * 289 * @return unmodifiable set of bonded devices, or null on error 290 * @hide 291 */ 292 public Set<BluetoothDevice> getBondedDevices() { 293 try { 294 return toDeviceSet(mService.listBonds()); 295 } catch (RemoteException e) {Log.e(TAG, "", e);} 296 return null; 297 } 298 299 /** 300 * Create a listening, secure RFCOMM Bluetooth socket. 301 * <p>A remote device connecting to this socket will be authenticated and 302 * communication on this socket will be encrypted. 303 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 304 * connections to listening {@link BluetoothServerSocket}. 305 * <p>Valid RFCOMM channels are in range 1 to 30. 306 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 307 * @param channel RFCOMM channel to listen on 308 * @return a listening RFCOMM BluetoothServerSocket 309 * @throws IOException on error, for example Bluetooth not available, or 310 * insufficient permissions, or channel in use. 311 */ 312 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException { 313 BluetoothServerSocket socket = new BluetoothServerSocket( 314 BluetoothSocket.TYPE_RFCOMM, true, true, channel); 315 try { 316 socket.mSocket.bindListen(); 317 } catch (IOException e) { 318 try { 319 socket.close(); 320 } catch (IOException e2) { } 321 throw e; 322 } 323 return socket; 324 } 325 326 /** 327 * Construct an unencrypted, unauthenticated, RFCOMM server socket. 328 * Call #accept to retrieve connections to this socket. 329 * @return An RFCOMM BluetoothServerSocket 330 * @throws IOException On error, for example Bluetooth not available, or 331 * insufficient permissions. 332 * @hide 333 */ 334 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException { 335 BluetoothServerSocket socket = new BluetoothServerSocket( 336 BluetoothSocket.TYPE_RFCOMM, false, false, port); 337 try { 338 socket.mSocket.bindListen(); 339 } catch (IOException e) { 340 try { 341 socket.close(); 342 } catch (IOException e2) { } 343 throw e; 344 } 345 return socket; 346 } 347 348 /** 349 * Construct a SCO server socket. 350 * Call #accept to retrieve connections to this socket. 351 * @return A SCO BluetoothServerSocket 352 * @throws IOException On error, for example Bluetooth not available, or 353 * insufficient permissions. 354 * @hide 355 */ 356 public static BluetoothServerSocket listenUsingScoOn() throws IOException { 357 BluetoothServerSocket socket = new BluetoothServerSocket( 358 BluetoothSocket.TYPE_SCO, false, false, -1); 359 try { 360 socket.mSocket.bindListen(); 361 } catch (IOException e) { 362 try { 363 socket.close(); 364 } catch (IOException e2) { } 365 throw e; 366 } 367 return socket; 368 } 369 370 private Set<BluetoothDevice> toDeviceSet(String[] addresses) { 371 Set<BluetoothDevice> devices = new HashSet<BluetoothDevice>(addresses.length); 372 for (int i = 0; i < addresses.length; i++) { 373 devices.add(getRemoteDevice(addresses[i])); 374 } 375 return Collections.unmodifiableSet(devices); 376 } 377} 378