• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.bluetooth;
18 
19 import android.annotation.SdkConstant;
20 import android.annotation.SdkConstant.SdkConstantType;
21 import android.content.Context;
22 import android.os.Binder;
23 import android.os.IBinder;
24 import android.os.Message;
25 import android.os.ParcelUuid;
26 import android.os.RemoteException;
27 import android.os.ServiceManager;
28 import android.util.Log;
29 import android.util.Pair;
30 
31 import java.io.IOException;
32 import java.lang.ref.WeakReference;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collections;
36 import java.util.HashSet;
37 import java.util.HashMap;
38 import java.util.LinkedList;
39 import java.util.Map;
40 import java.util.Random;
41 import java.util.Set;
42 import java.util.UUID;
43 
44 /**
45  * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
46  * lets you perform fundamental Bluetooth tasks, such as initiate
47  * device discovery, query a list of bonded (paired) devices,
48  * instantiate a {@link BluetoothDevice} using a known MAC address, and create
49  * a {@link BluetoothServerSocket} to listen for connection requests from other
50  * devices, and start a scan for Bluetooth LE devices.
51  *
52  * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
53  * adapter, when running on JELLY_BEAN_MR1 and below, call the
54  * static {@link #getDefaultAdapter} method; when running on JELLY_BEAN_MR2 and
55  * higher, retrieve it through
56  * {@link android.content.Context#getSystemService} with
57  * {@link android.content.Context#BLUETOOTH_SERVICE}.
58  * Fundamentally, this is your starting point for all
59  * Bluetooth actions. Once you have the local adapter, you can get a set of
60  * {@link BluetoothDevice} objects representing all paired devices with
61  * {@link #getBondedDevices()}; start device discovery with
62  * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
63  * listen for incoming connection requests with
64  * {@link #listenUsingRfcommWithServiceRecord(String,UUID)}; or start a scan for
65  * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
66  *
67  * <p class="note"><strong>Note:</strong>
68  * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
69  * permission and some also require the
70  * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
71  *
72  * <div class="special reference">
73  * <h3>Developer Guides</h3>
74  * <p>For more information about using Bluetooth, read the
75  * <a href="{@docRoot}guide/topics/wireless/bluetooth.html">Bluetooth</a> developer guide.</p>
76  * </div>
77  *
78  * {@see BluetoothDevice}
79  * {@see BluetoothServerSocket}
80  */
81 public final class BluetoothAdapter {
82     private static final String TAG = "BluetoothAdapter";
83     private static final boolean DBG = true;
84     private static final boolean VDBG = false;
85 
86     /**
87      * Sentinel error value for this class. Guaranteed to not equal any other
88      * integer constant in this class. Provided as a convenience for functions
89      * that require a sentinel error value, for example:
90      * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
91      * BluetoothAdapter.ERROR)</code>
92      */
93     public static final int ERROR = Integer.MIN_VALUE;
94 
95     /**
96      * Broadcast Action: The state of the local Bluetooth adapter has been
97      * changed.
98      * <p>For example, Bluetooth has been turned on or off.
99      * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
100      * #EXTRA_PREVIOUS_STATE} containing the new and old states
101      * respectively.
102      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
103      */
104     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
105     public static final String ACTION_STATE_CHANGED =
106             "android.bluetooth.adapter.action.STATE_CHANGED";
107 
108     /**
109      * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
110      * intents to request the current power state. Possible values are:
111      * {@link #STATE_OFF},
112      * {@link #STATE_TURNING_ON},
113      * {@link #STATE_ON},
114      * {@link #STATE_TURNING_OFF},
115      */
116     public static final String EXTRA_STATE =
117             "android.bluetooth.adapter.extra.STATE";
118     /**
119      * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
120      * intents to request the previous power state. Possible values are:
121      * {@link #STATE_OFF},
122      * {@link #STATE_TURNING_ON},
123      * {@link #STATE_ON},
124      * {@link #STATE_TURNING_OFF},
125      */
126     public static final String EXTRA_PREVIOUS_STATE =
127             "android.bluetooth.adapter.extra.PREVIOUS_STATE";
128 
129     /**
130      * Indicates the local Bluetooth adapter is off.
131      */
132     public static final int STATE_OFF = 10;
133     /**
134      * Indicates the local Bluetooth adapter is turning on. However local
135      * clients should wait for {@link #STATE_ON} before attempting to
136      * use the adapter.
137      */
138     public static final int STATE_TURNING_ON = 11;
139     /**
140      * Indicates the local Bluetooth adapter is on, and ready for use.
141      */
142     public static final int STATE_ON = 12;
143     /**
144      * Indicates the local Bluetooth adapter is turning off. Local clients
145      * should immediately attempt graceful disconnection of any remote links.
146      */
147     public static final int STATE_TURNING_OFF = 13;
148 
149     /**
150      * Activity Action: Show a system activity that requests discoverable mode.
151      * This activity will also request the user to turn on Bluetooth if it
152      * is not currently enabled.
153      * <p>Discoverable mode is equivalent to {@link
154      * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
155      * this Bluetooth adapter when they perform a discovery.
156      * <p>For privacy, Android is not discoverable by default.
157      * <p>The sender of this Intent can optionally use extra field {@link
158      * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
159      * discoverability. Currently the default duration is 120 seconds, and
160      * maximum duration is capped at 300 seconds for each request.
161      * <p>Notification of the result of this activity is posted using the
162      * {@link android.app.Activity#onActivityResult} callback. The
163      * <code>resultCode</code>
164      * will be the duration (in seconds) of discoverability or
165      * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
166      * discoverability or an error has occurred.
167      * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
168      * for global notification whenever the scan mode changes. For example, an
169      * application can be notified when the device has ended discoverability.
170      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
171      */
172     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
173     public static final String ACTION_REQUEST_DISCOVERABLE =
174             "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
175 
176     /**
177      * Used as an optional int extra field in {@link
178      * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
179      * for discoverability in seconds. The current default is 120 seconds, and
180      * requests over 300 seconds will be capped. These values could change.
181      */
182     public static final String EXTRA_DISCOVERABLE_DURATION =
183             "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
184 
185     /**
186      * Activity Action: Show a system activity that allows the user to turn on
187      * Bluetooth.
188      * <p>This system activity will return once Bluetooth has completed turning
189      * on, or the user has decided not to turn Bluetooth on.
190      * <p>Notification of the result of this activity is posted using the
191      * {@link android.app.Activity#onActivityResult} callback. The
192      * <code>resultCode</code>
193      * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
194      * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
195      * has rejected the request or an error has occurred.
196      * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
197      * for global notification whenever Bluetooth is turned on or off.
198      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
199      */
200     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
201     public static final String ACTION_REQUEST_ENABLE =
202             "android.bluetooth.adapter.action.REQUEST_ENABLE";
203 
204     /**
205      * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
206      * has changed.
207      * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
208      * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
209      * respectively.
210      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
211      */
212     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
213     public static final String ACTION_SCAN_MODE_CHANGED =
214             "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
215 
216     /**
217      * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
218      * intents to request the current scan mode. Possible values are:
219      * {@link #SCAN_MODE_NONE},
220      * {@link #SCAN_MODE_CONNECTABLE},
221      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
222      */
223     public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
224     /**
225      * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
226      * intents to request the previous scan mode. Possible values are:
227      * {@link #SCAN_MODE_NONE},
228      * {@link #SCAN_MODE_CONNECTABLE},
229      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
230      */
231     public static final String EXTRA_PREVIOUS_SCAN_MODE =
232             "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
233 
234     /**
235      * Indicates that both inquiry scan and page scan are disabled on the local
236      * Bluetooth adapter. Therefore this device is neither discoverable
237      * nor connectable from remote Bluetooth devices.
238      */
239     public static final int SCAN_MODE_NONE = 20;
240     /**
241      * Indicates that inquiry scan is disabled, but page scan is enabled on the
242      * local Bluetooth adapter. Therefore this device is not discoverable from
243      * remote Bluetooth devices, but is connectable from remote devices that
244      * have previously discovered this device.
245      */
246     public static final int SCAN_MODE_CONNECTABLE = 21;
247     /**
248      * Indicates that both inquiry scan and page scan are enabled on the local
249      * Bluetooth adapter. Therefore this device is both discoverable and
250      * connectable from remote Bluetooth devices.
251      */
252     public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
253 
254 
255     /**
256      * Broadcast Action: The local Bluetooth adapter has started the remote
257      * device discovery process.
258      * <p>This usually involves an inquiry scan of about 12 seconds, followed
259      * by a page scan of each new device to retrieve its Bluetooth name.
260      * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
261      * remote Bluetooth devices are found.
262      * <p>Device discovery is a heavyweight procedure. New connections to
263      * remote Bluetooth devices should not be attempted while discovery is in
264      * progress, and existing connections will experience limited bandwidth
265      * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
266      * discovery.
267      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
268      */
269     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
270     public static final String ACTION_DISCOVERY_STARTED =
271             "android.bluetooth.adapter.action.DISCOVERY_STARTED";
272     /**
273      * Broadcast Action: The local Bluetooth adapter has finished the device
274      * discovery process.
275      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
276      */
277     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
278     public static final String ACTION_DISCOVERY_FINISHED =
279             "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
280 
281     /**
282      * Broadcast Action: The local Bluetooth adapter has changed its friendly
283      * Bluetooth name.
284      * <p>This name is visible to remote Bluetooth devices.
285      * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
286      * the name.
287      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
288      */
289     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
290     public static final String ACTION_LOCAL_NAME_CHANGED =
291             "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
292     /**
293      * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
294      * intents to request the local Bluetooth name.
295      */
296     public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
297 
298     /**
299      * Intent used to broadcast the change in connection state of the local
300      * Bluetooth adapter to a profile of the remote device. When the adapter is
301      * not connected to any profiles of any remote devices and it attempts a
302      * connection to a profile this intent will sent. Once connected, this intent
303      * will not be sent for any more connection attempts to any profiles of any
304      * remote device. When the adapter disconnects from the last profile its
305      * connected to of any remote device, this intent will be sent.
306      *
307      * <p> This intent is useful for applications that are only concerned about
308      * whether the local adapter is connected to any profile of any device and
309      * are not really concerned about which profile. For example, an application
310      * which displays an icon to display whether Bluetooth is connected or not
311      * can use this intent.
312      *
313      * <p>This intent will have 3 extras:
314      * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
315      * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
316      * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
317      *
318      * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
319      * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
320      * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
321      *
322      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
323      */
324     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
325     public static final String ACTION_CONNECTION_STATE_CHANGED =
326         "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
327 
328     /**
329      * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
330      *
331      * This extra represents the current connection state.
332      */
333     public static final String EXTRA_CONNECTION_STATE =
334         "android.bluetooth.adapter.extra.CONNECTION_STATE";
335 
336     /**
337      * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
338      *
339      * This extra represents the previous connection state.
340      */
341     public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
342           "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
343 
344     /** The profile is in disconnected state */
345     public static final int STATE_DISCONNECTED  = 0;
346     /** The profile is in connecting state */
347     public static final int STATE_CONNECTING    = 1;
348     /** The profile is in connected state */
349     public static final int STATE_CONNECTED     = 2;
350     /** The profile is in disconnecting state */
351     public static final int STATE_DISCONNECTING = 3;
352 
353     /** @hide */
354     public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
355 
356     private static final int ADDRESS_LENGTH = 17;
357 
358     /**
359      * Lazily initialized singleton. Guaranteed final after first object
360      * constructed.
361      */
362     private static BluetoothAdapter sAdapter;
363 
364     private final IBluetoothManager mManagerService;
365     private IBluetooth mService;
366 
367     private final Map<LeScanCallback, GattCallbackWrapper> mLeScanClients;
368 
369     /**
370      * Get a handle to the default local Bluetooth adapter.
371      * <p>Currently Android only supports one Bluetooth adapter, but the API
372      * could be extended to support more. This will always return the default
373      * adapter.
374      * @return the default local adapter, or null if Bluetooth is not supported
375      *         on this hardware platform
376      */
getDefaultAdapter()377     public static synchronized BluetoothAdapter getDefaultAdapter() {
378         if (sAdapter == null) {
379             IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
380             if (b != null) {
381                 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
382                 sAdapter = new BluetoothAdapter(managerService);
383             } else {
384                 Log.e(TAG, "Bluetooth binder is null");
385             }
386         }
387         return sAdapter;
388     }
389 
390     /**
391      * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
392      */
BluetoothAdapter(IBluetoothManager managerService)393     BluetoothAdapter(IBluetoothManager managerService) {
394 
395         if (managerService == null) {
396             throw new IllegalArgumentException("bluetooth manager service is null");
397         }
398         try {
399             mService = managerService.registerAdapter(mManagerCallback);
400         } catch (RemoteException e) {Log.e(TAG, "", e);}
401         mManagerService = managerService;
402         mLeScanClients = new HashMap<LeScanCallback, GattCallbackWrapper>();
403     }
404 
405     /**
406      * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
407      * address.
408      * <p>Valid Bluetooth hardware addresses must be upper case, in a format
409      * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
410      * available to validate a Bluetooth address.
411      * <p>A {@link BluetoothDevice} will always be returned for a valid
412      * hardware address, even if this adapter has never seen that device.
413      *
414      * @param address valid Bluetooth MAC address
415      * @throws IllegalArgumentException if address is invalid
416      */
getRemoteDevice(String address)417     public BluetoothDevice getRemoteDevice(String address) {
418         return new BluetoothDevice(address);
419     }
420 
421     /**
422      * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
423      * address.
424      * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
425      * expects the address in network byte order (MSB first).
426      * <p>A {@link BluetoothDevice} will always be returned for a valid
427      * hardware address, even if this adapter has never seen that device.
428      *
429      * @param address Bluetooth MAC address (6 bytes)
430      * @throws IllegalArgumentException if address is invalid
431      */
getRemoteDevice(byte[] address)432     public BluetoothDevice getRemoteDevice(byte[] address) {
433         if (address == null || address.length != 6) {
434             throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
435         }
436         return new BluetoothDevice(String.format("%02X:%02X:%02X:%02X:%02X:%02X",
437                 address[0], address[1], address[2], address[3], address[4], address[5]));
438     }
439 
440     /**
441      * Return true if Bluetooth is currently enabled and ready for use.
442      * <p>Equivalent to:
443      * <code>getBluetoothState() == STATE_ON</code>
444      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
445      *
446      * @return true if the local adapter is turned on
447      */
isEnabled()448     public boolean isEnabled() {
449 
450         try {
451             synchronized(mManagerCallback) {
452                 if (mService != null) return mService.isEnabled();
453             }
454         } catch (RemoteException e) {Log.e(TAG, "", e);}
455         return false;
456     }
457 
458     /**
459      * Get the current state of the local Bluetooth adapter.
460      * <p>Possible return values are
461      * {@link #STATE_OFF},
462      * {@link #STATE_TURNING_ON},
463      * {@link #STATE_ON},
464      * {@link #STATE_TURNING_OFF}.
465      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
466      *
467      * @return current state of Bluetooth adapter
468      */
getState()469     public int getState() {
470         try {
471             synchronized(mManagerCallback) {
472                 if (mService != null)
473                 {
474                     int state=  mService.getState();
475                     if (VDBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + state);
476                     return state;
477                 }
478                 // TODO(BT) there might be a small gap during STATE_TURNING_ON that
479                 //          mService is null, handle that case
480             }
481         } catch (RemoteException e) {Log.e(TAG, "", e);}
482         if (DBG) Log.d(TAG, "" + hashCode() + ": getState() :  mService = null. Returning STATE_OFF");
483         return STATE_OFF;
484     }
485 
486     /**
487      * Turn on the local Bluetooth adapter&mdash;do not use without explicit
488      * user action to turn on Bluetooth.
489      * <p>This powers on the underlying Bluetooth hardware, and starts all
490      * Bluetooth system services.
491      * <p class="caution"><strong>Bluetooth should never be enabled without
492      * direct user consent</strong>. If you want to turn on Bluetooth in order
493      * to create a wireless connection, you should use the {@link
494      * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
495      * user permission to turn on Bluetooth. The {@link #enable()} method is
496      * provided only for applications that include a user interface for changing
497      * system settings, such as a "power manager" app.</p>
498      * <p>This is an asynchronous call: it will return immediately, and
499      * clients should listen for {@link #ACTION_STATE_CHANGED}
500      * to be notified of subsequent adapter state changes. If this call returns
501      * true, then the adapter state will immediately transition from {@link
502      * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
503      * later transition to either {@link #STATE_OFF} or {@link
504      * #STATE_ON}. If this call returns false then there was an
505      * immediate problem that will prevent the adapter from being turned on -
506      * such as Airplane mode, or the adapter is already turned on.
507      * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
508      * permission
509      *
510      * @return true to indicate adapter startup has begun, or false on
511      *         immediate error
512      */
enable()513     public boolean enable() {
514         if (isEnabled() == true){
515             if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
516             return true;
517         }
518         try {
519             return mManagerService.enable();
520         } catch (RemoteException e) {Log.e(TAG, "", e);}
521         return false;
522     }
523 
524     /**
525      * Turn off the local Bluetooth adapter&mdash;do not use without explicit
526      * user action to turn off Bluetooth.
527      * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
528      * system services, and powers down the underlying Bluetooth hardware.
529      * <p class="caution"><strong>Bluetooth should never be disabled without
530      * direct user consent</strong>. The {@link #disable()} method is
531      * provided only for applications that include a user interface for changing
532      * system settings, such as a "power manager" app.</p>
533      * <p>This is an asynchronous call: it will return immediately, and
534      * clients should listen for {@link #ACTION_STATE_CHANGED}
535      * to be notified of subsequent adapter state changes. If this call returns
536      * true, then the adapter state will immediately transition from {@link
537      * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
538      * later transition to either {@link #STATE_OFF} or {@link
539      * #STATE_ON}. If this call returns false then there was an
540      * immediate problem that will prevent the adapter from being turned off -
541      * such as the adapter already being turned off.
542      * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
543      * permission
544      *
545      * @return true to indicate adapter shutdown has begun, or false on
546      *         immediate error
547      */
disable()548     public boolean disable() {
549         try {
550             return mManagerService.disable(true);
551         } catch (RemoteException e) {Log.e(TAG, "", e);}
552         return false;
553     }
554 
555     /**
556      * Turn off the local Bluetooth adapter and don't persist the setting.
557      *
558      * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
559      * permission
560      *
561      * @return true to indicate adapter shutdown has begun, or false on
562      *         immediate error
563      * @hide
564      */
disable(boolean persist)565     public boolean disable(boolean persist) {
566 
567         try {
568             return mManagerService.disable(persist);
569         } catch (RemoteException e) {Log.e(TAG, "", e);}
570         return false;
571     }
572 
573     /**
574      * Returns the hardware address of the local Bluetooth adapter.
575      * <p>For example, "00:11:22:AA:BB:CC".
576      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
577      *
578      * @return Bluetooth hardware address as string
579      */
getAddress()580     public String getAddress() {
581         try {
582             return mManagerService.getAddress();
583         } catch (RemoteException e) {Log.e(TAG, "", e);}
584         return null;
585     }
586 
587     /**
588      * Get the friendly Bluetooth name of the local Bluetooth adapter.
589      * <p>This name is visible to remote Bluetooth devices.
590      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
591      *
592      * @return the Bluetooth name, or null on error
593      */
getName()594     public String getName() {
595         try {
596             return mManagerService.getName();
597         } catch (RemoteException e) {Log.e(TAG, "", e);}
598         return null;
599     }
600 
601     /**
602      * Get the UUIDs supported by the local Bluetooth adapter.
603      *
604      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
605      *
606      * @return the UUIDs supported by the local Bluetooth Adapter.
607      * @hide
608      */
getUuids()609     public ParcelUuid[] getUuids() {
610         if (getState() != STATE_ON) return null;
611         try {
612             synchronized(mManagerCallback) {
613                 if (mService != null) return mService.getUuids();
614             }
615         } catch (RemoteException e) {Log.e(TAG, "", e);}
616         return null;
617     }
618 
619     /**
620      * Set the friendly Bluetooth name of the local Bluetooth adapter.
621      * <p>This name is visible to remote Bluetooth devices.
622      * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
623      * encoding, although many remote devices can only display the first
624      * 40 characters, and some may be limited to just 20.
625      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
626      * will return false. After turning on Bluetooth,
627      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
628      * to get the updated value.
629      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
630      *
631      * @param name a valid Bluetooth name
632      * @return     true if the name was set, false otherwise
633      */
setName(String name)634     public boolean setName(String name) {
635         if (getState() != STATE_ON) return false;
636         try {
637             synchronized(mManagerCallback) {
638                 if (mService != null) return mService.setName(name);
639             }
640         } catch (RemoteException e) {Log.e(TAG, "", e);}
641         return false;
642     }
643 
644     /**
645      * Get the current Bluetooth scan mode of the local Bluetooth adapter.
646      * <p>The Bluetooth scan mode determines if the local adapter is
647      * connectable and/or discoverable from remote Bluetooth devices.
648      * <p>Possible values are:
649      * {@link #SCAN_MODE_NONE},
650      * {@link #SCAN_MODE_CONNECTABLE},
651      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
652      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
653      * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
654      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
655      * to get the updated value.
656      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
657      *
658      * @return scan mode
659      */
getScanMode()660     public int getScanMode() {
661         if (getState() != STATE_ON) return SCAN_MODE_NONE;
662         try {
663             synchronized(mManagerCallback) {
664                 if (mService != null) return mService.getScanMode();
665             }
666         } catch (RemoteException e) {Log.e(TAG, "", e);}
667         return SCAN_MODE_NONE;
668     }
669 
670     /**
671      * Set the Bluetooth scan mode of the local Bluetooth adapter.
672      * <p>The Bluetooth scan mode determines if the local adapter is
673      * connectable and/or discoverable from remote Bluetooth devices.
674      * <p>For privacy reasons, discoverable mode is automatically turned off
675      * after <code>duration</code> seconds. For example, 120 seconds should be
676      * enough for a remote device to initiate and complete its discovery
677      * process.
678      * <p>Valid scan mode values are:
679      * {@link #SCAN_MODE_NONE},
680      * {@link #SCAN_MODE_CONNECTABLE},
681      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
682      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
683      * will return false. After turning on Bluetooth,
684      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
685      * to get the updated value.
686      * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}
687      * <p>Applications cannot set the scan mode. They should use
688      * <code>startActivityForResult(
689      * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
690      * </code>instead.
691      *
692      * @param mode valid scan mode
693      * @param duration time in seconds to apply scan mode, only used for
694      *                 {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
695      * @return     true if the scan mode was set, false otherwise
696      * @hide
697      */
setScanMode(int mode, int duration)698     public boolean setScanMode(int mode, int duration) {
699         if (getState() != STATE_ON) return false;
700         try {
701             synchronized(mManagerCallback) {
702                 if (mService != null) return mService.setScanMode(mode, duration);
703             }
704         } catch (RemoteException e) {Log.e(TAG, "", e);}
705         return false;
706     }
707 
708     /** @hide */
setScanMode(int mode)709     public boolean setScanMode(int mode) {
710         if (getState() != STATE_ON) return false;
711         /* getDiscoverableTimeout() to use the latest from NV than use 0 */
712         return setScanMode(mode, getDiscoverableTimeout());
713     }
714 
715     /** @hide */
getDiscoverableTimeout()716     public int getDiscoverableTimeout() {
717         if (getState() != STATE_ON) return -1;
718         try {
719             synchronized(mManagerCallback) {
720                 if (mService != null) return mService.getDiscoverableTimeout();
721             }
722         } catch (RemoteException e) {Log.e(TAG, "", e);}
723         return -1;
724     }
725 
726     /** @hide */
setDiscoverableTimeout(int timeout)727     public void setDiscoverableTimeout(int timeout) {
728         if (getState() != STATE_ON) return;
729         try {
730             synchronized(mManagerCallback) {
731                 if (mService != null) mService.setDiscoverableTimeout(timeout);
732             }
733         } catch (RemoteException e) {Log.e(TAG, "", e);}
734     }
735 
736     /**
737      * Start the remote device discovery process.
738      * <p>The discovery process usually involves an inquiry scan of about 12
739      * seconds, followed by a page scan of each new device to retrieve its
740      * Bluetooth name.
741      * <p>This is an asynchronous call, it will return immediately. Register
742      * for {@link #ACTION_DISCOVERY_STARTED} and {@link
743      * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
744      * discovery starts and completes. Register for {@link
745      * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
746      * are found.
747      * <p>Device discovery is a heavyweight procedure. New connections to
748      * remote Bluetooth devices should not be attempted while discovery is in
749      * progress, and existing connections will experience limited bandwidth
750      * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
751      * discovery. Discovery is not managed by the Activity,
752      * but is run as a system service, so an application should always call
753      * {@link BluetoothAdapter#cancelDiscovery()} even if it
754      * did not directly request a discovery, just to be sure.
755      * <p>Device discovery will only find remote devices that are currently
756      * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
757      * not discoverable by default, and need to be entered into a special mode.
758      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
759      * will return false. After turning on Bluetooth,
760      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
761      * to get the updated value.
762      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
763      *
764      * @return true on success, false on error
765      */
startDiscovery()766     public boolean startDiscovery() {
767         if (getState() != STATE_ON) return false;
768         try {
769             synchronized(mManagerCallback) {
770                 if (mService != null) return mService.startDiscovery();
771             }
772         } catch (RemoteException e) {Log.e(TAG, "", e);}
773         return false;
774     }
775 
776     /**
777      * Cancel the current device discovery process.
778      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
779      * <p>Because discovery is a heavyweight procedure for the Bluetooth
780      * adapter, this method should always be called before attempting to connect
781      * to a remote device with {@link
782      * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
783      * the  Activity, but is run as a system service, so an application should
784      * always call cancel discovery even if it did not directly request a
785      * discovery, just to be sure.
786      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
787      * will return false. After turning on Bluetooth,
788      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
789      * to get the updated value.
790      *
791      * @return true on success, false on error
792      */
cancelDiscovery()793     public boolean cancelDiscovery() {
794         if (getState() != STATE_ON) return false;
795         try {
796             synchronized(mManagerCallback) {
797                 if (mService != null) return mService.cancelDiscovery();
798             }
799         } catch (RemoteException e) {Log.e(TAG, "", e);}
800         return false;
801     }
802 
803     /**
804      * Return true if the local Bluetooth adapter is currently in the device
805      * discovery process.
806      * <p>Device discovery is a heavyweight procedure. New connections to
807      * remote Bluetooth devices should not be attempted while discovery is in
808      * progress, and existing connections will experience limited bandwidth
809      * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
810      * discovery.
811      * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
812      * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
813      * starts or completes.
814      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
815      * will return false. After turning on Bluetooth,
816      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
817      * to get the updated value.
818      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
819      *
820      * @return true if discovering
821      */
isDiscovering()822     public boolean isDiscovering() {
823         if (getState() != STATE_ON) return false;
824         try {
825             synchronized(mManagerCallback) {
826                 if (mService != null ) return mService.isDiscovering();
827             }
828         } catch (RemoteException e) {Log.e(TAG, "", e);}
829         return false;
830     }
831 
832     /**
833      * Return the set of {@link BluetoothDevice} objects that are bonded
834      * (paired) to the local adapter.
835      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
836      * will return an empty set. After turning on Bluetooth,
837      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
838      * to get the updated value.
839      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
840      *
841      * @return unmodifiable set of {@link BluetoothDevice}, or null on error
842      */
getBondedDevices()843     public Set<BluetoothDevice> getBondedDevices() {
844         if (getState() != STATE_ON) {
845             return toDeviceSet(new BluetoothDevice[0]);
846         }
847         try {
848             synchronized(mManagerCallback) {
849                 if (mService != null) return toDeviceSet(mService.getBondedDevices());
850             }
851             return toDeviceSet(new BluetoothDevice[0]);
852         } catch (RemoteException e) {Log.e(TAG, "", e);}
853         return null;
854     }
855 
856     /**
857      * Get the current connection state of the local Bluetooth adapter.
858      * This can be used to check whether the local Bluetooth adapter is connected
859      * to any profile of any other remote Bluetooth Device.
860      *
861      * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
862      * intent to get the connection state of the adapter.
863      *
864      * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED},
865      * {@link #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
866      *
867      * @hide
868      */
getConnectionState()869     public int getConnectionState() {
870         if (getState() != STATE_ON) return BluetoothAdapter.STATE_DISCONNECTED;
871         try {
872             synchronized(mManagerCallback) {
873                 if (mService != null) return mService.getAdapterConnectionState();
874             }
875         } catch (RemoteException e) {Log.e(TAG, "getConnectionState:", e);}
876         return BluetoothAdapter.STATE_DISCONNECTED;
877     }
878 
879     /**
880      * Get the current connection state of a profile.
881      * This function can be used to check whether the local Bluetooth adapter
882      * is connected to any remote device for a specific profile.
883      * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
884      * {@link BluetoothProfile#A2DP}.
885      *
886      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
887      *
888      * <p> Return value can be one of
889      * {@link BluetoothProfile#STATE_DISCONNECTED},
890      * {@link BluetoothProfile#STATE_CONNECTING},
891      * {@link BluetoothProfile#STATE_CONNECTED},
892      * {@link BluetoothProfile#STATE_DISCONNECTING}
893      */
getProfileConnectionState(int profile)894     public int getProfileConnectionState(int profile) {
895         if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED;
896         try {
897             synchronized(mManagerCallback) {
898                 if (mService != null) return mService.getProfileConnectionState(profile);
899             }
900         } catch (RemoteException e) {
901             Log.e(TAG, "getProfileConnectionState:", e);
902         }
903         return BluetoothProfile.STATE_DISCONNECTED;
904     }
905 
906     /**
907      * Create a listening, secure RFCOMM Bluetooth socket.
908      * <p>A remote device connecting to this socket will be authenticated and
909      * communication on this socket will be encrypted.
910      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
911      * connections from a listening {@link BluetoothServerSocket}.
912      * <p>Valid RFCOMM channels are in range 1 to 30.
913      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
914      * @param channel RFCOMM channel to listen on
915      * @return a listening RFCOMM BluetoothServerSocket
916      * @throws IOException on error, for example Bluetooth not available, or
917      *                     insufficient permissions, or channel in use.
918      * @hide
919      */
listenUsingRfcommOn(int channel)920     public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
921         BluetoothServerSocket socket = new BluetoothServerSocket(
922                 BluetoothSocket.TYPE_RFCOMM, true, true, channel);
923         int errno = socket.mSocket.bindListen();
924         if (errno != 0) {
925             //TODO(BT): Throw the same exception error code
926             // that the previous code was using.
927             //socket.mSocket.throwErrnoNative(errno);
928             throw new IOException("Error: " + errno);
929         }
930         return socket;
931     }
932 
933     /**
934      * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
935      * <p>A remote device connecting to this socket will be authenticated and
936      * communication on this socket will be encrypted.
937      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
938      * connections from a listening {@link BluetoothServerSocket}.
939      * <p>The system will assign an unused RFCOMM channel to listen on.
940      * <p>The system will also register a Service Discovery
941      * Protocol (SDP) record with the local SDP server containing the specified
942      * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
943      * can use the same UUID to query our SDP server and discover which channel
944      * to connect to. This SDP record will be removed when this socket is
945      * closed, or if this application closes unexpectedly.
946      * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
947      * connect to this socket from another device using the same {@link UUID}.
948      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
949      * @param name service name for SDP record
950      * @param uuid uuid for SDP record
951      * @return a listening RFCOMM BluetoothServerSocket
952      * @throws IOException on error, for example Bluetooth not available, or
953      *                     insufficient permissions, or channel in use.
954      */
listenUsingRfcommWithServiceRecord(String name, UUID uuid)955     public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
956             throws IOException {
957         return createNewRfcommSocketAndRecord(name, uuid, true, true);
958     }
959 
960     /**
961      * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
962      * <p>The link key is not required to be authenticated, i.e the communication may be
963      * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices,
964      * the link will be encrypted, as encryption is mandartory.
965      * For legacy devices (pre Bluetooth 2.1 devices) the link will not
966      * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
967      * encrypted and authenticated communication channel is desired.
968      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
969      * connections from a listening {@link BluetoothServerSocket}.
970      * <p>The system will assign an unused RFCOMM channel to listen on.
971      * <p>The system will also register a Service Discovery
972      * Protocol (SDP) record with the local SDP server containing the specified
973      * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
974      * can use the same UUID to query our SDP server and discover which channel
975      * to connect to. This SDP record will be removed when this socket is
976      * closed, or if this application closes unexpectedly.
977      * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
978      * connect to this socket from another device using the same {@link UUID}.
979      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
980      * @param name service name for SDP record
981      * @param uuid uuid for SDP record
982      * @return a listening RFCOMM BluetoothServerSocket
983      * @throws IOException on error, for example Bluetooth not available, or
984      *                     insufficient permissions, or channel in use.
985      */
listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)986     public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
987             throws IOException {
988         return createNewRfcommSocketAndRecord(name, uuid, false, false);
989     }
990 
991      /**
992      * Create a listening, encrypted,
993      * RFCOMM Bluetooth socket with Service Record.
994      * <p>The link will be encrypted, but the link key is not required to be authenticated
995      * i.e the communication is vulnerable to Man In the Middle attacks. Use
996      * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
997      * <p> Use this socket if authentication of link key is not possible.
998      * For example, for Bluetooth 2.1 devices, if any of the devices does not have
999      * an input and output capability or just has the ability to display a numeric key,
1000      * a secure socket connection is not possible and this socket can be used.
1001      * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
1002      * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
1003      * For more details, refer to the Security Model section 5.2 (vol 3) of
1004      * Bluetooth Core Specification version 2.1 + EDR.
1005      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1006      * connections from a listening {@link BluetoothServerSocket}.
1007      * <p>The system will assign an unused RFCOMM channel to listen on.
1008      * <p>The system will also register a Service Discovery
1009      * Protocol (SDP) record with the local SDP server containing the specified
1010      * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1011      * can use the same UUID to query our SDP server and discover which channel
1012      * to connect to. This SDP record will be removed when this socket is
1013      * closed, or if this application closes unexpectedly.
1014      * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1015      * connect to this socket from another device using the same {@link UUID}.
1016      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1017      * @param name service name for SDP record
1018      * @param uuid uuid for SDP record
1019      * @return a listening RFCOMM BluetoothServerSocket
1020      * @throws IOException on error, for example Bluetooth not available, or
1021      *                     insufficient permissions, or channel in use.
1022      * @hide
1023      */
listenUsingEncryptedRfcommWithServiceRecord( String name, UUID uuid)1024     public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(
1025             String name, UUID uuid) throws IOException {
1026         return createNewRfcommSocketAndRecord(name, uuid, false, true);
1027     }
1028 
1029 
createNewRfcommSocketAndRecord(String name, UUID uuid, boolean auth, boolean encrypt)1030     private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
1031             boolean auth, boolean encrypt) throws IOException {
1032         BluetoothServerSocket socket;
1033         socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth,
1034                         encrypt, new ParcelUuid(uuid));
1035         socket.setServiceName(name);
1036         int errno = socket.mSocket.bindListen();
1037         if (errno != 0) {
1038             //TODO(BT): Throw the same exception error code
1039             // that the previous code was using.
1040             //socket.mSocket.throwErrnoNative(errno);
1041             throw new IOException("Error: " + errno);
1042         }
1043         return socket;
1044     }
1045 
1046     /**
1047      * Construct an unencrypted, unauthenticated, RFCOMM server socket.
1048      * Call #accept to retrieve connections to this socket.
1049      * @return An RFCOMM BluetoothServerSocket
1050      * @throws IOException On error, for example Bluetooth not available, or
1051      *                     insufficient permissions.
1052      * @hide
1053      */
listenUsingInsecureRfcommOn(int port)1054     public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
1055         BluetoothServerSocket socket = new BluetoothServerSocket(
1056                 BluetoothSocket.TYPE_RFCOMM, false, false, port);
1057         int errno = socket.mSocket.bindListen();
1058         if (errno != 0) {
1059             //TODO(BT): Throw the same exception error code
1060             // that the previous code was using.
1061             //socket.mSocket.throwErrnoNative(errno);
1062             throw new IOException("Error: " + errno);
1063         }
1064         return socket;
1065     }
1066 
1067      /**
1068      * Construct an encrypted, RFCOMM server socket.
1069      * Call #accept to retrieve connections to this socket.
1070      * @return An RFCOMM BluetoothServerSocket
1071      * @throws IOException On error, for example Bluetooth not available, or
1072      *                     insufficient permissions.
1073      * @hide
1074      */
listenUsingEncryptedRfcommOn(int port)1075     public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port)
1076             throws IOException {
1077         BluetoothServerSocket socket = new BluetoothServerSocket(
1078                 BluetoothSocket.TYPE_RFCOMM, false, true, port);
1079         int errno = socket.mSocket.bindListen();
1080         if (errno < 0) {
1081             //TODO(BT): Throw the same exception error code
1082             // that the previous code was using.
1083             //socket.mSocket.throwErrnoNative(errno);
1084             throw new IOException("Error: " + errno);
1085         }
1086         return socket;
1087     }
1088 
1089     /**
1090      * Construct a SCO server socket.
1091      * Call #accept to retrieve connections to this socket.
1092      * @return A SCO BluetoothServerSocket
1093      * @throws IOException On error, for example Bluetooth not available, or
1094      *                     insufficient permissions.
1095      * @hide
1096      */
listenUsingScoOn()1097     public static BluetoothServerSocket listenUsingScoOn() throws IOException {
1098         BluetoothServerSocket socket = new BluetoothServerSocket(
1099                 BluetoothSocket.TYPE_SCO, false, false, -1);
1100         int errno = socket.mSocket.bindListen();
1101         if (errno < 0) {
1102             //TODO(BT): Throw the same exception error code
1103             // that the previous code was using.
1104             //socket.mSocket.throwErrnoNative(errno);
1105         }
1106         return socket;
1107     }
1108 
1109     /**
1110      * Read the local Out of Band Pairing Data
1111      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1112      *
1113      * @return Pair<byte[], byte[]> of Hash and Randomizer
1114      *
1115      * @hide
1116      */
readOutOfBandData()1117     public Pair<byte[], byte[]> readOutOfBandData() {
1118         if (getState() != STATE_ON) return null;
1119         //TODO(BT
1120         /*
1121         try {
1122             byte[] hash;
1123             byte[] randomizer;
1124 
1125             byte[] ret = mService.readOutOfBandData();
1126 
1127             if (ret  == null || ret.length != 32) return null;
1128 
1129             hash = Arrays.copyOfRange(ret, 0, 16);
1130             randomizer = Arrays.copyOfRange(ret, 16, 32);
1131 
1132             if (DBG) {
1133                 Log.d(TAG, "readOutOfBandData:" + Arrays.toString(hash) +
1134                   ":" + Arrays.toString(randomizer));
1135             }
1136             return new Pair<byte[], byte[]>(hash, randomizer);
1137 
1138         } catch (RemoteException e) {Log.e(TAG, "", e);}*/
1139         return null;
1140     }
1141 
1142     /**
1143      * Get the profile proxy object associated with the profile.
1144      *
1145      * <p>Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
1146      * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, or
1147      * {@link BluetoothProfile#GATT_SERVER}. Clients must implement
1148      * {@link BluetoothProfile.ServiceListener} to get notified of
1149      * the connection status and to get the proxy object.
1150      *
1151      * @param context Context of the application
1152      * @param listener The service Listener for connection callbacks.
1153      * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH},
1154      *                {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}.
1155      * @return true on success, false on error
1156      */
getProfileProxy(Context context, BluetoothProfile.ServiceListener listener, int profile)1157     public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
1158                                    int profile) {
1159         if (context == null || listener == null) return false;
1160 
1161         if (profile == BluetoothProfile.HEADSET) {
1162             BluetoothHeadset headset = new BluetoothHeadset(context, listener);
1163             return true;
1164         } else if (profile == BluetoothProfile.A2DP) {
1165             BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
1166             return true;
1167         } else if (profile == BluetoothProfile.INPUT_DEVICE) {
1168             BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
1169             return true;
1170         } else if (profile == BluetoothProfile.PAN) {
1171             BluetoothPan pan = new BluetoothPan(context, listener);
1172             return true;
1173         } else if (profile == BluetoothProfile.HEALTH) {
1174             BluetoothHealth health = new BluetoothHealth(context, listener);
1175             return true;
1176         } else {
1177             return false;
1178         }
1179     }
1180 
1181     /**
1182      * Close the connection of the profile proxy to the Service.
1183      *
1184      * <p> Clients should call this when they are no longer using
1185      * the proxy obtained from {@link #getProfileProxy}.
1186      * Profile can be one of  {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET} or
1187      * {@link BluetoothProfile#A2DP}
1188      *
1189      * @param profile
1190      * @param proxy Profile proxy object
1191      */
closeProfileProxy(int profile, BluetoothProfile proxy)1192     public void closeProfileProxy(int profile, BluetoothProfile proxy) {
1193         if (proxy == null) return;
1194 
1195         switch (profile) {
1196             case BluetoothProfile.HEADSET:
1197                 BluetoothHeadset headset = (BluetoothHeadset)proxy;
1198                 headset.close();
1199                 break;
1200             case BluetoothProfile.A2DP:
1201                 BluetoothA2dp a2dp = (BluetoothA2dp)proxy;
1202                 a2dp.close();
1203                 break;
1204             case BluetoothProfile.INPUT_DEVICE:
1205                 BluetoothInputDevice iDev = (BluetoothInputDevice)proxy;
1206                 iDev.close();
1207                 break;
1208             case BluetoothProfile.PAN:
1209                 BluetoothPan pan = (BluetoothPan)proxy;
1210                 pan.close();
1211                 break;
1212             case BluetoothProfile.HEALTH:
1213                 BluetoothHealth health = (BluetoothHealth)proxy;
1214                 health.close();
1215                 break;
1216            case BluetoothProfile.GATT:
1217                 BluetoothGatt gatt = (BluetoothGatt)proxy;
1218                 gatt.close();
1219                 break;
1220             case BluetoothProfile.GATT_SERVER:
1221                 BluetoothGattServer gattServer = (BluetoothGattServer)proxy;
1222                 gattServer.close();
1223                 break;
1224         }
1225     }
1226 
1227     final private IBluetoothManagerCallback mManagerCallback =
1228         new IBluetoothManagerCallback.Stub() {
1229             public void onBluetoothServiceUp(IBluetooth bluetoothService) {
1230                 if (VDBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
1231                 synchronized (mManagerCallback) {
1232                     mService = bluetoothService;
1233                     for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
1234                         try {
1235                             if (cb != null) {
1236                                 cb.onBluetoothServiceUp(bluetoothService);
1237                             } else {
1238                                 Log.d(TAG, "onBluetoothServiceUp: cb is null!!!");
1239                             }
1240                         } catch (Exception e)  { Log.e(TAG,"",e);}
1241                     }
1242                 }
1243             }
1244 
1245             public void onBluetoothServiceDown() {
1246                 if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
1247                 synchronized (mManagerCallback) {
1248                     mService = null;
1249                     for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
1250                         try {
1251                             if (cb != null) {
1252                                 cb.onBluetoothServiceDown();
1253                             } else {
1254                                 Log.d(TAG, "onBluetoothServiceDown: cb is null!!!");
1255                             }
1256                         } catch (Exception e)  { Log.e(TAG,"",e);}
1257                     }
1258                 }
1259             }
1260     };
1261 
1262     /**
1263      * Enable the Bluetooth Adapter, but don't auto-connect devices
1264      * and don't persist state. Only for use by system applications.
1265      * @hide
1266      */
enableNoAutoConnect()1267     public boolean enableNoAutoConnect() {
1268         if (isEnabled() == true){
1269             if (DBG) Log.d(TAG, "enableNoAutoConnect(): BT is already enabled..!");
1270             return true;
1271         }
1272         try {
1273             return mManagerService.enableNoAutoConnect();
1274         } catch (RemoteException e) {Log.e(TAG, "", e);}
1275         return false;
1276     }
1277 
1278     /**
1279      * Enable control of the Bluetooth Adapter for a single application.
1280      *
1281      * <p>Some applications need to use Bluetooth for short periods of time to
1282      * transfer data but don't want all the associated implications like
1283      * automatic connection to headsets etc.
1284      *
1285      * <p> Multiple applications can call this. This is reference counted and
1286      * Bluetooth disabled only when no one else is using it. There will be no UI
1287      * shown to the user while bluetooth is being enabled. Any user action will
1288      * override this call. For example, if user wants Bluetooth on and the last
1289      * user of this API wanted to disable Bluetooth, Bluetooth will not be
1290      * turned off.
1291      *
1292      * <p> This API is only meant to be used by internal applications. Third
1293      * party applications but use {@link #enable} and {@link #disable} APIs.
1294      *
1295      * <p> If this API returns true, it means the callback will be called.
1296      * The callback will be called with the current state of Bluetooth.
1297      * If the state is not what was requested, an internal error would be the
1298      * reason. If Bluetooth is already on and if this function is called to turn
1299      * it on, the api will return true and a callback will be called.
1300      *
1301      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1302      *
1303      * @param on True for on, false for off.
1304      * @param callback The callback to notify changes to the state.
1305      * @hide
1306      */
changeApplicationBluetoothState(boolean on, BluetoothStateChangeCallback callback)1307     public boolean changeApplicationBluetoothState(boolean on,
1308                                                    BluetoothStateChangeCallback callback) {
1309         if (callback == null) return false;
1310 
1311         //TODO(BT)
1312         /*
1313         try {
1314             return mService.changeApplicationBluetoothState(on, new
1315                     StateChangeCallbackWrapper(callback), new Binder());
1316         } catch (RemoteException e) {
1317             Log.e(TAG, "changeBluetoothState", e);
1318         }*/
1319         return false;
1320     }
1321 
1322     /**
1323      * @hide
1324      */
1325     public interface BluetoothStateChangeCallback {
onBluetoothStateChange(boolean on)1326         public void onBluetoothStateChange(boolean on);
1327     }
1328 
1329     /**
1330      * @hide
1331      */
1332     public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
1333         private BluetoothStateChangeCallback mCallback;
1334 
StateChangeCallbackWrapper(BluetoothStateChangeCallback callback)1335         StateChangeCallbackWrapper(BluetoothStateChangeCallback
1336                 callback) {
1337             mCallback = callback;
1338         }
1339 
1340         @Override
onBluetoothStateChange(boolean on)1341         public void onBluetoothStateChange(boolean on) {
1342             mCallback.onBluetoothStateChange(on);
1343         }
1344     }
1345 
toDeviceSet(BluetoothDevice[] devices)1346     private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
1347         Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
1348         return Collections.unmodifiableSet(deviceSet);
1349     }
1350 
finalize()1351     protected void finalize() throws Throwable {
1352         try {
1353             mManagerService.unregisterAdapter(mManagerCallback);
1354         } catch (RemoteException e) {
1355             Log.e(TAG, "", e);
1356         } finally {
1357             super.finalize();
1358         }
1359     }
1360 
1361 
1362     /**
1363      * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
1364      * <p>Alphabetic characters must be uppercase to be valid.
1365      *
1366      * @param address Bluetooth address as string
1367      * @return true if the address is valid, false otherwise
1368      */
checkBluetoothAddress(String address)1369     public static boolean checkBluetoothAddress(String address) {
1370         if (address == null || address.length() != ADDRESS_LENGTH) {
1371             return false;
1372         }
1373         for (int i = 0; i < ADDRESS_LENGTH; i++) {
1374             char c = address.charAt(i);
1375             switch (i % 3) {
1376             case 0:
1377             case 1:
1378                 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
1379                     // hex character, OK
1380                     break;
1381                 }
1382                 return false;
1383             case 2:
1384                 if (c == ':') {
1385                     break;  // OK
1386                 }
1387                 return false;
1388             }
1389         }
1390         return true;
1391     }
1392 
getBluetoothManager()1393     /*package*/ IBluetoothManager getBluetoothManager() {
1394             return mManagerService;
1395     }
1396 
1397     private ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = new ArrayList<IBluetoothManagerCallback>();
1398 
getBluetoothService(IBluetoothManagerCallback cb)1399     /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
1400         synchronized (mManagerCallback) {
1401             if (cb == null) {
1402                 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
1403             } else if (!mProxyServiceStateCallbacks.contains(cb)) {
1404                 mProxyServiceStateCallbacks.add(cb);
1405             }
1406         }
1407         return mService;
1408     }
1409 
removeServiceStateCallback(IBluetoothManagerCallback cb)1410     /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
1411         synchronized (mManagerCallback) {
1412             mProxyServiceStateCallbacks.remove(cb);
1413         }
1414     }
1415 
1416     /**
1417      * Callback interface used to deliver LE scan results.
1418      *
1419      * @see #startLeScan(LeScanCallback)
1420      * @see #startLeScan(UUID[], LeScanCallback)
1421      */
1422     public interface LeScanCallback {
1423         /**
1424          * Callback reporting an LE device found during a device scan initiated
1425          * by the {@link BluetoothAdapter#startLeScan} function.
1426          *
1427          * @param device Identifies the remote device
1428          * @param rssi The RSSI value for the remote device as reported by the
1429          *             Bluetooth hardware. 0 if no RSSI value is available.
1430          * @param scanRecord The content of the advertisement record offered by
1431          *                   the remote device.
1432          */
onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)1433         public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
1434     }
1435 
1436     /**
1437      * Starts a scan for Bluetooth LE devices.
1438      *
1439      * <p>Results of the scan are reported using the
1440      * {@link LeScanCallback#onLeScan} callback.
1441      *
1442      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
1443      *
1444      * @param callback the callback LE scan results are delivered
1445      * @return true, if the scan was started successfully
1446      */
startLeScan(LeScanCallback callback)1447     public boolean startLeScan(LeScanCallback callback) {
1448         return startLeScan(null, callback);
1449     }
1450 
1451     /**
1452      * Starts a scan for Bluetooth LE devices, looking for devices that
1453      * advertise given services.
1454      *
1455      * <p>Devices which advertise all specified services are reported using the
1456      * {@link LeScanCallback#onLeScan} callback.
1457      *
1458      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
1459      *
1460      * @param serviceUuids Array of services to look for
1461      * @param callback the callback LE scan results are delivered
1462      * @return true, if the scan was started successfully
1463      */
startLeScan(UUID[] serviceUuids, LeScanCallback callback)1464     public boolean startLeScan(UUID[] serviceUuids, LeScanCallback callback) {
1465         if (DBG) Log.d(TAG, "startLeScan(): " + serviceUuids);
1466 
1467         if (callback == null) {
1468             if (DBG) Log.e(TAG, "startLeScan: null callback");
1469             return false;
1470         }
1471 
1472         synchronized(mLeScanClients) {
1473             if (mLeScanClients.containsKey(callback)) {
1474                 if (DBG) Log.e(TAG, "LE Scan has already started");
1475                 return false;
1476             }
1477 
1478             try {
1479                 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
1480                 if (iGatt == null) {
1481                     // BLE is not supported
1482                     return false;
1483                 }
1484 
1485                 UUID uuid = UUID.randomUUID();
1486                 GattCallbackWrapper wrapper = new GattCallbackWrapper(this, callback, serviceUuids);
1487                 iGatt.registerClient(new ParcelUuid(uuid), wrapper);
1488                 if (wrapper.scanStarted()) {
1489                     mLeScanClients.put(callback, wrapper);
1490                     return true;
1491                 }
1492             } catch (RemoteException e) {
1493                 Log.e(TAG,"",e);
1494             }
1495         }
1496         return false;
1497     }
1498 
1499     /**
1500      * Stops an ongoing Bluetooth LE device scan.
1501      *
1502      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
1503      *
1504      * @param callback used to identify which scan to stop
1505      *        must be the same handle used to start the scan
1506      */
stopLeScan(LeScanCallback callback)1507     public void stopLeScan(LeScanCallback callback) {
1508         if (DBG) Log.d(TAG, "stopLeScan()");
1509         GattCallbackWrapper wrapper;
1510         synchronized(mLeScanClients) {
1511             wrapper = mLeScanClients.remove(callback);
1512             if (wrapper == null) return;
1513         }
1514         wrapper.stopLeScan();
1515     }
1516 
1517     /**
1518      * Bluetooth GATT interface callbacks
1519      */
1520     private static class GattCallbackWrapper extends IBluetoothGattCallback.Stub {
1521         private static final int LE_CALLBACK_REG_TIMEOUT = 2000;
1522         private static final int LE_CALLBACK_REG_WAIT_COUNT = 5;
1523 
1524         private final LeScanCallback mLeScanCb;
1525         // mLeHandle 0: not registered
1526         //           -1: scan stopped
1527         //           >0: registered and scan started
1528         private int mLeHandle;
1529         private final UUID[] mScanFilter;
1530         private WeakReference<BluetoothAdapter> mBluetoothAdapter;
1531 
GattCallbackWrapper(BluetoothAdapter bluetoothAdapter, LeScanCallback leScanCb, UUID[] uuid)1532         public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter,
1533                                    LeScanCallback leScanCb, UUID[] uuid) {
1534             mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter);
1535             mLeScanCb = leScanCb;
1536             mScanFilter = uuid;
1537             mLeHandle = 0;
1538         }
1539 
scanStarted()1540         public boolean scanStarted() {
1541             boolean started = false;
1542             synchronized(this) {
1543                 if (mLeHandle == -1) return false;
1544 
1545                 int count = 0;
1546                 // wait for callback registration and LE scan to start
1547                 while (mLeHandle == 0 && count < LE_CALLBACK_REG_WAIT_COUNT) {
1548                     try {
1549                         wait(LE_CALLBACK_REG_TIMEOUT);
1550                     } catch (InterruptedException e) {
1551                         Log.e(TAG, "Callback reg wait interrupted: " + e);
1552                     }
1553                     count++;
1554                 }
1555                 started = (mLeHandle > 0);
1556             }
1557             return started;
1558         }
1559 
stopLeScan()1560         public void stopLeScan() {
1561             synchronized(this) {
1562                 if (mLeHandle <= 0) {
1563                     Log.e(TAG, "Error state, mLeHandle: " + mLeHandle);
1564                     return;
1565                 }
1566                 BluetoothAdapter adapter = mBluetoothAdapter.get();
1567                 if (adapter != null) {
1568                     try {
1569                         IBluetoothGatt iGatt = adapter.getBluetoothManager().getBluetoothGatt();
1570                         iGatt.stopScan(mLeHandle, false);
1571                         iGatt.unregisterClient(mLeHandle);
1572                     } catch (RemoteException e) {
1573                         Log.e(TAG, "Failed to stop scan and unregister" + e);
1574                     }
1575                 } else {
1576                     Log.e(TAG, "stopLeScan, BluetoothAdapter is null");
1577                 }
1578                 mLeHandle = -1;
1579                 notifyAll();
1580             }
1581         }
1582 
1583         /**
1584          * Application interface registered - app is ready to go
1585          */
onClientRegistered(int status, int clientIf)1586         public void onClientRegistered(int status, int clientIf) {
1587             if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status +
1588                            " clientIf=" + clientIf);
1589             synchronized(this) {
1590                 if (mLeHandle == -1) {
1591                     if (DBG) Log.d(TAG, "onClientRegistered LE scan canceled");
1592                 }
1593 
1594                 if (status == BluetoothGatt.GATT_SUCCESS) {
1595                     mLeHandle = clientIf;
1596                     IBluetoothGatt iGatt = null;
1597                     try {
1598                         BluetoothAdapter adapter = mBluetoothAdapter.get();
1599                         if (adapter != null) {
1600                             iGatt = adapter.getBluetoothManager().getBluetoothGatt();
1601                             if (mScanFilter == null) {
1602                                 iGatt.startScan(mLeHandle, false);
1603                             } else {
1604                                 ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
1605                                 for(int i = 0; i != uuids.length; ++i) {
1606                                     uuids[i] = new ParcelUuid(mScanFilter[i]);
1607                                 }
1608                                 iGatt.startScanWithUuids(mLeHandle, false, uuids);
1609                             }
1610                         } else {
1611                             Log.e(TAG, "onClientRegistered, BluetoothAdapter null");
1612                             mLeHandle = -1;
1613                         }
1614                     } catch (RemoteException e) {
1615                         Log.e(TAG, "fail to start le scan: " + e);
1616                         mLeHandle = -1;
1617                     }
1618                     if (mLeHandle == -1) {
1619                         // registration succeeded but start scan failed
1620                         if (iGatt != null) {
1621                             try {
1622                                 iGatt.unregisterClient(mLeHandle);
1623                             } catch (RemoteException e) {
1624                                 Log.e(TAG, "fail to unregister callback: " + mLeHandle +
1625                                       " error: " + e);
1626                             }
1627                         }
1628                     }
1629                 } else {
1630                     // registration failed
1631                     mLeHandle = -1;
1632                 }
1633                 notifyAll();
1634             }
1635         }
1636 
onClientConnectionState(int status, int clientIf, boolean connected, String address)1637         public void onClientConnectionState(int status, int clientIf,
1638                                             boolean connected, String address) {
1639             // no op
1640         }
1641 
1642         /**
1643          * Callback reporting an LE scan result.
1644          * @hide
1645          */
onScanResult(String address, int rssi, byte[] advData)1646         public void onScanResult(String address, int rssi, byte[] advData) {
1647             if (DBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
1648 
1649             // Check null in case the scan has been stopped
1650             synchronized(this) {
1651                 if (mLeHandle <= 0) return;
1652             }
1653             try {
1654                 BluetoothAdapter adapter = mBluetoothAdapter.get();
1655                 if (adapter == null) {
1656                     Log.d(TAG, "onScanResult, BluetoothAdapter null");
1657                     return;
1658                 }
1659                 mLeScanCb.onLeScan(adapter.getRemoteDevice(address), rssi, advData);
1660             } catch (Exception ex) {
1661                 Log.w(TAG, "Unhandled exception: " + ex);
1662             }
1663         }
1664 
onGetService(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid)1665         public void onGetService(String address, int srvcType,
1666                                  int srvcInstId, ParcelUuid srvcUuid) {
1667             // no op
1668         }
1669 
onGetIncludedService(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int inclSrvcType, int inclSrvcInstId, ParcelUuid inclSrvcUuid)1670         public void onGetIncludedService(String address, int srvcType,
1671                                          int srvcInstId, ParcelUuid srvcUuid,
1672                                          int inclSrvcType, int inclSrvcInstId,
1673                                          ParcelUuid inclSrvcUuid) {
1674             // no op
1675         }
1676 
onGetCharacteristic(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int charProps)1677         public void onGetCharacteristic(String address, int srvcType,
1678                                         int srvcInstId, ParcelUuid srvcUuid,
1679                                         int charInstId, ParcelUuid charUuid,
1680                                         int charProps) {
1681             // no op
1682         }
1683 
onGetDescriptor(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, ParcelUuid descUuid)1684         public void onGetDescriptor(String address, int srvcType,
1685                                     int srvcInstId, ParcelUuid srvcUuid,
1686                                     int charInstId, ParcelUuid charUuid,
1687                                     ParcelUuid descUuid) {
1688             // no op
1689         }
1690 
onSearchComplete(String address, int status)1691         public void onSearchComplete(String address, int status) {
1692             // no op
1693         }
1694 
onCharacteristicRead(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value)1695         public void onCharacteristicRead(String address, int status, int srvcType,
1696                                          int srvcInstId, ParcelUuid srvcUuid,
1697                                          int charInstId, ParcelUuid charUuid, byte[] value) {
1698             // no op
1699         }
1700 
onCharacteristicWrite(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid)1701         public void onCharacteristicWrite(String address, int status, int srvcType,
1702                                           int srvcInstId, ParcelUuid srvcUuid,
1703                                           int charInstId, ParcelUuid charUuid) {
1704             // no op
1705         }
1706 
onNotify(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value)1707         public void onNotify(String address, int srvcType,
1708                              int srvcInstId, ParcelUuid srvcUuid,
1709                              int charInstId, ParcelUuid charUuid,
1710                              byte[] value) {
1711             // no op
1712         }
1713 
onDescriptorRead(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, ParcelUuid descrUuid, byte[] value)1714         public void onDescriptorRead(String address, int status, int srvcType,
1715                                      int srvcInstId, ParcelUuid srvcUuid,
1716                                      int charInstId, ParcelUuid charUuid,
1717                                      ParcelUuid descrUuid, byte[] value) {
1718             // no op
1719         }
1720 
onDescriptorWrite(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, ParcelUuid descrUuid)1721         public void onDescriptorWrite(String address, int status, int srvcType,
1722                                       int srvcInstId, ParcelUuid srvcUuid,
1723                                       int charInstId, ParcelUuid charUuid,
1724                                       ParcelUuid descrUuid) {
1725             // no op
1726         }
1727 
onExecuteWrite(String address, int status)1728         public void onExecuteWrite(String address, int status) {
1729             // no op
1730         }
1731 
onReadRemoteRssi(String address, int rssi, int status)1732         public void onReadRemoteRssi(String address, int rssi, int status) {
1733             // no op
1734         }
1735     }
1736 
1737 }
1738