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