blob: 5a182f0fb45d51c07a0acfd5ec4e9326e9035694 [file] [log] [blame]
Nick Pellybd022f42009-08-14 18:33:38 -07001/*
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 *
Nick Pelly45e27042009-08-19 11:00:00 -070030 * <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
Nick Pellybd022f42009-08-14 18:33:38 -070039 */
40public final class BluetoothAdapter {
41 private static final String TAG = "BluetoothAdapter";
42
Nick Pelly45e27042009-08-19 11:00:00 -070043 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -070044 public static final int BLUETOOTH_STATE_OFF = 0;
Nick Pelly45e27042009-08-19 11:00:00 -070045 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -070046 public static final int BLUETOOTH_STATE_TURNING_ON = 1;
Nick Pelly45e27042009-08-19 11:00:00 -070047 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -070048 public static final int BLUETOOTH_STATE_ON = 2;
Nick Pelly45e27042009-08-19 11:00:00 -070049 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -070050 public static final int BLUETOOTH_STATE_TURNING_OFF = 3;
51
52 /** Inquiry scan and page scan are both off.
Nick Pelly45e27042009-08-19 11:00:00 -070053 * Device is neither discoverable nor connectable
54 * @hide */
Nick Pellybd022f42009-08-14 18:33:38 -070055 public static final int SCAN_MODE_NONE = 0;
56 /** Page scan is on, inquiry scan is off.
Nick Pelly45e27042009-08-19 11:00:00 -070057 * Device is connectable, but not discoverable
58 * @hide*/
Nick Pellybd022f42009-08-14 18:33:38 -070059 public static final int SCAN_MODE_CONNECTABLE = 1;
60 /** Page scan and inquiry scan are on.
Nick Pelly45e27042009-08-19 11:00:00 -070061 * Device is connectable and discoverable
62 * @hide*/
Nick Pellybd022f42009-08-14 18:33:38 -070063 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 3;
64
Nick Pelly45e27042009-08-19 11:00:00 -070065 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -070066 public static final int RESULT_FAILURE = -1;
Nick Pelly45e27042009-08-19 11:00:00 -070067 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -070068 public static final int RESULT_SUCCESS = 0;
69
Nick Pelly45e27042009-08-19 11:00:00 -070070 /** The user will be prompted to enter a pin
71 * @hide */
Nick Pellybd022f42009-08-14 18:33:38 -070072 public static final int PAIRING_VARIANT_PIN = 0;
Nick Pelly45e27042009-08-19 11:00:00 -070073 /** The user will be prompted to enter a passkey
74 * @hide */
Nick Pellybd022f42009-08-14 18:33:38 -070075 public static final int PAIRING_VARIANT_PASSKEY = 1;
Nick Pelly45e27042009-08-19 11:00:00 -070076 /** The user will be prompted to confirm the passkey displayed on the screen
77 * @hide */
Nick Pellybd022f42009-08-14 18:33:38 -070078 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 /**
Nick Pelly45e27042009-08-19 11:00:00 -070094 * 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.
Nick Pellybd022f42009-08-14 18:33:38 -0700100 * @param address valid Bluetooth MAC address
Nick Pelly45e27042009-08-19 11:00:00 -0700101 * @throws IllegalArgumentException if address is invalid
Nick Pellybd022f42009-08-14 18:33:38 -0700102 */
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.
Nick Pelly45e27042009-08-19 11:00:00 -0700111 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700112 */
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.
Nick Pelly45e27042009-08-19 11:00:00 -0700124 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700125 */
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.
Nick Pelly45e27042009-08-19 11:00:00 -0700142 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700143 */
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.
Nick Pelly45e27042009-08-19 11:00:00 -0700156 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700157 */
158 public boolean disable() {
159 try {
160 return mService.disable(true);
161 } catch (RemoteException e) {Log.e(TAG, "", e);}
162 return false;
163 }
164
Nick Pelly45e27042009-08-19 11:00:00 -0700165 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -0700166 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.
Nick Pelly45e27042009-08-19 11:00:00 -0700180 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700181 */
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.
Nick Pelly45e27042009-08-19 11:00:00 -0700197 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700198 */
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
Nick Pelly45e27042009-08-19 11:00:00 -0700210 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700211 */
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_*
Nick Pelly45e27042009-08-19 11:00:00 -0700223 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700224 */
225 public void setScanMode(int scanMode) {
226 try {
227 mService.setScanMode(scanMode);
228 } catch (RemoteException e) {Log.e(TAG, "", e);}
229 }
230
Nick Pelly45e27042009-08-19 11:00:00 -0700231 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -0700232 public int getDiscoverableTimeout() {
233 try {
234 return mService.getDiscoverableTimeout();
235 } catch (RemoteException e) {Log.e(TAG, "", e);}
236 return -1;
237 }
238
Nick Pelly45e27042009-08-19 11:00:00 -0700239 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -0700240 public void setDiscoverableTimeout(int timeout) {
241 try {
242 mService.setDiscoverableTimeout(timeout);
243 } catch (RemoteException e) {Log.e(TAG, "", e);}
244 }
245
Nick Pelly45e27042009-08-19 11:00:00 -0700246 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -0700247 public boolean startDiscovery() {
248 try {
249 return mService.startDiscovery();
250 } catch (RemoteException e) {Log.e(TAG, "", e);}
251 return false;
252 }
253
Nick Pelly45e27042009-08-19 11:00:00 -0700254 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -0700255 public void cancelDiscovery() {
256 try {
257 mService.cancelDiscovery();
258 } catch (RemoteException e) {Log.e(TAG, "", e);}
259 }
260
Nick Pelly45e27042009-08-19 11:00:00 -0700261 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -0700262 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
Nick Pelly45e27042009-08-19 11:00:00 -0700290 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700291 */
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 /**
Nick Pelly45e27042009-08-19 11:00:00 -0700300 * Create a listening, secure RFCOMM Bluetooth socket.
301 * <p>A remote device connecting to this socket will be authenticated and
Nick Pellybd022f42009-08-14 18:33:38 -0700302 * communication on this socket will be encrypted.
Nick Pelly45e27042009-08-19 11:00:00 -0700303 * <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.
Nick Pellycf440592009-09-08 10:12:06 -0700306 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pelly45e27042009-08-19 11:00:00 -0700307 * @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.
Nick Pellybd022f42009-08-14 18:33:38 -0700311 */
Nick Pelly45e27042009-08-19 11:00:00 -0700312 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
Nick Pellybd022f42009-08-14 18:33:38 -0700313 BluetoothServerSocket socket = new BluetoothServerSocket(
Nick Pelly45e27042009-08-19 11:00:00 -0700314 BluetoothSocket.TYPE_RFCOMM, true, true, channel);
Nick Pellybd022f42009-08-14 18:33:38 -0700315 try {
Nick Pelly71c3c782009-09-02 11:51:35 -0700316 socket.mSocket.bindListen();
Nick Pellybd022f42009-08-14 18:33:38 -0700317 } 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.
Nick Pelly45e27042009-08-19 11:00:00 -0700332 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700333 */
334 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
335 BluetoothServerSocket socket = new BluetoothServerSocket(
336 BluetoothSocket.TYPE_RFCOMM, false, false, port);
337 try {
Nick Pelly71c3c782009-09-02 11:51:35 -0700338 socket.mSocket.bindListen();
Nick Pellybd022f42009-08-14 18:33:38 -0700339 } 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.
Nick Pelly45e27042009-08-19 11:00:00 -0700354 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700355 */
356 public static BluetoothServerSocket listenUsingScoOn() throws IOException {
357 BluetoothServerSocket socket = new BluetoothServerSocket(
358 BluetoothSocket.TYPE_SCO, false, false, -1);
359 try {
Nick Pelly71c3c782009-09-02 11:51:35 -0700360 socket.mSocket.bindListen();
Nick Pellybd022f42009-08-14 18:33:38 -0700361 } 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}