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