blob: a64c6d72d43c3ca83cb3ad2ddce0698015245739 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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 {
The Android Open Source Project10592532009-03-18 17:39:46 -070034
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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040 /** 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
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -070077 /* 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 private static final String TAG = "BluetoothDevice";
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 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 /**
The Android Open Source Project10592532009-03-18 17:39:46 -0700100 * Is Bluetooth currently turned on.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 *
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 /**
The Android Open Source Project10592532009-03-18 17:39:46 -0700112 * 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 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 * Enable the Bluetooth device.
125 * Turn on the underlying hardware.
The Android Open Source Project10592532009-03-18 17:39:46 -0700126 * 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.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 * @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() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 try {
The Android Open Source Project10592532009-03-18 17:39:46 -0700135 return mService.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 } 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 {
The Android Open Source Project10592532009-03-18 17:39:46 -0700148 return mService.disable(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 } 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 /**
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() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 try {
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700228 return mService.startDiscovery();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 } 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 /**
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700247 * Removes the remote device and the pairing information associated
248 * with it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 *
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 */
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700254 public boolean removeBond(String address) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 try {
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700256 return mService.removeBond(address);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 } 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 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 * 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 public int getRemoteClass(String address) {
343 try {
344 return mService.getRemoteClass(address);
345 } catch (RemoteException e) {Log.e(TAG, "", e);}
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700346 return BluetoothError.ERROR_IPC;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 }
348
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700349 public String[] getRemoteUuids(String address) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 try {
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700351 return mService.getRemoteUuids(address);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352 } catch (RemoteException e) {Log.e(TAG, "", e);}
353 return null;
354 }
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700355
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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 }
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 }
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700369
370 public boolean setPasskey(String address, int passkey) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 try {
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700372 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);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 } 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 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415
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}