blob: c942a27e8cd1fea26cc39ce5f2bba1483fe23c39 [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
77 private static final String TAG = "BluetoothDevice";
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 private final IBluetoothDevice mService;
80 /**
81 * @hide - hide this because it takes a parameter of type
82 * IBluetoothDevice, which is a System private class.
83 * Also note that Context.getSystemService is a factory that
84 * returns a BlueToothDevice. That is the right way to get
85 * a BluetoothDevice.
86 */
87 public BluetoothDevice(IBluetoothDevice service) {
88 mService = service;
89 }
90
91 /**
The Android Open Source Project10592532009-03-18 17:39:46 -070092 * Is Bluetooth currently turned on.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 *
94 * @return true if Bluetooth enabled, false otherwise.
95 */
96 public boolean isEnabled() {
97 try {
98 return mService.isEnabled();
99 } catch (RemoteException e) {Log.e(TAG, "", e);}
100 return false;
101 }
102
103 /**
The Android Open Source Project10592532009-03-18 17:39:46 -0700104 * Get the current state of Bluetooth.
105 *
106 * @return One of BLUETOOTH_STATE_ or BluetoothError.ERROR.
107 */
108 public int getBluetoothState() {
109 try {
110 return mService.getBluetoothState();
111 } catch (RemoteException e) {Log.e(TAG, "", e);}
112 return BluetoothError.ERROR;
113 }
114
115 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 * Enable the Bluetooth device.
117 * Turn on the underlying hardware.
The Android Open Source Project10592532009-03-18 17:39:46 -0700118 * This is an asynchronous call,
119 * BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION can be used to check if
120 * and when the device is sucessfully enabled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 * @return false if we cannot enable the Bluetooth device. True does not
122 * imply the device was enabled, it only implies that so far there were no
123 * problems.
124 */
125 public boolean enable() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 try {
The Android Open Source Project10592532009-03-18 17:39:46 -0700127 return mService.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 } catch (RemoteException e) {Log.e(TAG, "", e);}
129 return false;
130 }
131
132 /**
133 * Disable the Bluetooth device.
134 * This turns off the underlying hardware.
135 *
136 * @return true if successful, false otherwise.
137 */
138 public boolean disable() {
139 try {
The Android Open Source Project10592532009-03-18 17:39:46 -0700140 return mService.disable(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 } catch (RemoteException e) {Log.e(TAG, "", e);}
142 return false;
143 }
144
145 public String getAddress() {
146 try {
147 return mService.getAddress();
148 } catch (RemoteException e) {Log.e(TAG, "", e);}
149 return null;
150 }
151
152 /**
153 * Get the friendly Bluetooth name of this device.
154 *
155 * This name is visible to remote Bluetooth devices. Currently it is only
156 * possible to retrieve the Bluetooth name when Bluetooth is enabled.
157 *
158 * @return the Bluetooth name, or null if there was a problem.
159 */
160 public String getName() {
161 try {
162 return mService.getName();
163 } catch (RemoteException e) {Log.e(TAG, "", e);}
164 return null;
165 }
166
167 /**
168 * Set the friendly Bluetooth name of this device.
169 *
170 * This name is visible to remote Bluetooth devices. The Bluetooth Service
171 * is responsible for persisting this name.
172 *
173 * @param name the name to set
174 * @return true, if the name was successfully set. False otherwise.
175 */
176 public boolean setName(String name) {
177 try {
178 return mService.setName(name);
179 } catch (RemoteException e) {Log.e(TAG, "", e);}
180 return false;
181 }
182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 /**
184 * Get the current scan mode.
185 * Used to determine if the local device is connectable and/or discoverable
186 * @return Scan mode, one of SCAN_MODE_* or an error code
187 */
188 public int getScanMode() {
189 try {
190 return mService.getScanMode();
191 } catch (RemoteException e) {Log.e(TAG, "", e);}
192 return BluetoothError.ERROR_IPC;
193 }
194
195 /**
196 * Set the current scan mode.
197 * Used to make the local device connectable and/or discoverable
198 * @param scanMode One of SCAN_MODE_*
199 */
200 public void setScanMode(int scanMode) {
201 try {
202 mService.setScanMode(scanMode);
203 } catch (RemoteException e) {Log.e(TAG, "", e);}
204 }
205
206 public int getDiscoverableTimeout() {
207 try {
208 return mService.getDiscoverableTimeout();
209 } catch (RemoteException e) {Log.e(TAG, "", e);}
210 return -1;
211 }
212 public void setDiscoverableTimeout(int timeout) {
213 try {
214 mService.setDiscoverableTimeout(timeout);
215 } catch (RemoteException e) {Log.e(TAG, "", e);}
216 }
217
218 public boolean startDiscovery() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 try {
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700220 return mService.startDiscovery();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 } catch (RemoteException e) {Log.e(TAG, "", e);}
222 return false;
223 }
224
225 public void cancelDiscovery() {
226 try {
227 mService.cancelDiscovery();
228 } catch (RemoteException e) {Log.e(TAG, "", e);}
229 }
230
231 public boolean isDiscovering() {
232 try {
233 return mService.isDiscovering();
234 } catch (RemoteException e) {Log.e(TAG, "", e);}
235 return false;
236 }
237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 /**
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700239 * Removes the remote device and the pairing information associated
240 * with it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 *
242 * @param address the Bluetooth hardware address you want to disconnect.
243 * @return true if the device was disconnected, false otherwise and on
244 * error.
245 */
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700246 public boolean removeBond(String address) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 try {
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700248 return mService.removeBond(address);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 } catch (RemoteException e) {Log.e(TAG, "", e);}
250 return false;
251 }
252
253 /**
254 * Create a bonding with a remote bluetooth device.
255 *
256 * This is an asynchronous call. The result of this bonding attempt can be
257 * observed through BluetoothIntent.BOND_STATE_CHANGED_ACTION intents.
258 *
259 * @param address the remote device Bluetooth address.
260 * @return false If there was an immediate problem creating the bonding,
261 * true otherwise.
262 */
263 public boolean createBond(String address) {
264 try {
265 return mService.createBond(address);
266 } catch (RemoteException e) {Log.e(TAG, "", e);}
267 return false;
268 }
269
270 /**
271 * Cancel an in-progress bonding request started with createBond.
272 */
273 public boolean cancelBondProcess(String address) {
274 try {
275 return mService.cancelBondProcess(address);
276 } catch (RemoteException e) {Log.e(TAG, "", e);}
277 return false;
278 }
279
280 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 * List remote devices that are bonded (paired) to the local device.
282 *
283 * Bonding (pairing) is the process by which the user enters a pin code for
284 * the device, which generates a shared link key, allowing for
285 * authentication and encryption of future connections. In Android we
286 * require bonding before RFCOMM or SCO connections can be made to a remote
287 * device.
288 *
289 * This function lists which remote devices we have a link key for. It does
290 * not cause any RF transmission, and does not check if the remote device
291 * still has it's link key with us. If the other side no longer has its
292 * link key then the RFCOMM or SCO connection attempt will result in an
293 * error.
294 *
295 * This function does not check if the remote device is in range.
296 *
297 * Remote devices that have an in-progress bonding attempt are not
298 * returned.
299 *
300 * @return bluetooth hardware addresses of remote devices that are
301 * bonded. Array size is 0 if no devices are bonded. Null on error.
302 */
303 public String[] listBonds() {
304 try {
305 return mService.listBonds();
306 } catch (RemoteException e) {Log.e(TAG, "", e);}
307 return null;
308 }
309
310 /**
311 * Get the bonding state of a remote device.
312 *
313 * Result is one of:
314 * BluetoothError.*
315 * BOND_*
316 *
317 * @param address Bluetooth hardware address of the remote device to check.
318 * @return Result code
319 */
320 public int getBondState(String address) {
321 try {
322 return mService.getBondState(address);
323 } catch (RemoteException e) {Log.e(TAG, "", e);}
324 return BluetoothError.ERROR_IPC;
325 }
326
327 public String getRemoteName(String address) {
328 try {
329 return mService.getRemoteName(address);
330 } catch (RemoteException e) {Log.e(TAG, "", e);}
331 return null;
332 }
333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 public int getRemoteClass(String address) {
335 try {
336 return mService.getRemoteClass(address);
337 } catch (RemoteException e) {Log.e(TAG, "", e);}
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700338 return BluetoothError.ERROR_IPC;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 }
340
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700341 public String[] getRemoteUuids(String address) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 try {
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700343 return mService.getRemoteUuids(address);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 } catch (RemoteException e) {Log.e(TAG, "", e);}
345 return null;
346 }
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700347
348 public int getRemoteServiceChannel(String address, String uuid) {
349 try {
350 return mService.getRemoteServiceChannel(address, uuid);
351 } catch (RemoteException e) {Log.e(TAG, "", e);}
352 return BluetoothError.ERROR_IPC;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 }
354
355 public boolean setPin(String address, byte[] pin) {
356 try {
357 return mService.setPin(address, pin);
358 } catch (RemoteException e) {Log.e(TAG, "", e);}
359 return false;
360 }
Jaikumar Ganesh12cae392009-07-17 14:45:22 -0700361 public boolean cancelPin(String address) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 try {
Jaikumar Ganesh12cae392009-07-17 14:45:22 -0700363 return mService.cancelPin(address);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 } catch (RemoteException e) {Log.e(TAG, "", e);}
365 return false;
366 }
367
368 /**
369 * Check that a pin is valid and convert to byte array.
370 *
371 * Bluetooth pin's are 1 to 16 bytes of UTF8 characters.
372 * @param pin pin as java String
373 * @return the pin code as a UTF8 byte array, or null if it is an invalid
374 * Bluetooth pin.
375 */
376 public static byte[] convertPinToBytes(String pin) {
377 if (pin == null) {
378 return null;
379 }
380 byte[] pinBytes;
381 try {
382 pinBytes = pin.getBytes("UTF8");
383 } catch (UnsupportedEncodingException uee) {
384 Log.e(TAG, "UTF8 not supported?!?"); // this should not happen
385 return null;
386 }
387 if (pinBytes.length <= 0 || pinBytes.length > 16) {
388 return null;
389 }
390 return pinBytes;
391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392
393 private static final int ADDRESS_LENGTH = 17;
394 /** Sanity check a bluetooth address, such as "00:43:A8:23:10:F0" */
395 public static boolean checkBluetoothAddress(String address) {
396 if (address == null || address.length() != ADDRESS_LENGTH) {
397 return false;
398 }
399 for (int i = 0; i < ADDRESS_LENGTH; i++) {
400 char c = address.charAt(i);
401 switch (i % 3) {
402 case 0:
403 case 1:
404 if (Character.digit(c, 16) != -1) {
405 break; // hex character, OK
406 }
407 return false;
408 case 2:
409 if (c == ':') {
410 break; // OK
411 }
412 return false;
413 }
414 }
415 return true;
416 }
417}