blob: 885b42f3b10cd7ad7df24806f5dd3f62254768ba [file] [log] [blame]
Nick Pellybd022f42009-08-14 18:33:38 -07001/*
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002 * Copyright (C) 2009-2016 The Android Open Source Project
Casper Bonde238e0f92015-04-09 09:24:48 +02003 * Copyright (C) 2015 Samsung LSI
Nick Pellybd022f42009-08-14 18:33:38 -07004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package android.bluetooth;
19
Tor Norbye2d497522015-04-23 17:10:21 -070020import android.Manifest;
21import android.annotation.IntDef;
22import android.annotation.RequiresPermission;
Nick Pellyde893f52009-09-08 13:15:33 -070023import android.annotation.SdkConstant;
24import android.annotation.SdkConstant.SdkConstantType;
Wei Wangd91f1932015-03-19 15:09:56 -070025import android.annotation.SystemApi;
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -070026import android.app.ActivityThread;
Wei Wang6d811182014-05-22 12:10:25 -070027import android.bluetooth.le.BluetoothLeAdvertiser;
28import android.bluetooth.le.BluetoothLeScanner;
Wei Wangaf74e662014-07-09 14:03:42 -070029import android.bluetooth.le.ScanCallback;
Wei Wangc3059cc2014-07-23 23:34:00 -070030import android.bluetooth.le.ScanFilter;
31import android.bluetooth.le.ScanRecord;
Wei Wang9fb17912014-07-01 15:10:06 -070032import android.bluetooth.le.ScanResult;
Wei Wangaf74e662014-07-09 14:03:42 -070033import android.bluetooth.le.ScanSettings;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070034import android.content.Context;
Adam Lesinski010bf372016-04-11 12:18:18 -070035import android.os.BatteryStats;
Wei Wang46ab7232015-05-07 16:25:33 -070036import android.os.Binder;
Nick Pellyf242b7b2009-10-08 00:12:45 +020037import android.os.IBinder;
Nick Pellyaef439e2009-09-28 12:33:17 -070038import android.os.ParcelUuid;
Nick Pellybd022f42009-08-14 18:33:38 -070039import android.os.RemoteException;
Adam Lesinski010bf372016-04-11 12:18:18 -070040import android.os.ResultReceiver;
Nick Pellyf242b7b2009-10-08 00:12:45 +020041import android.os.ServiceManager;
Adam Lesinski010bf372016-04-11 12:18:18 -070042import android.os.SynchronousResultReceiver;
Ajay Panickerb6e1daf2016-02-29 16:09:14 -080043import android.os.SystemProperties;
Nick Pellybd022f42009-08-14 18:33:38 -070044import android.util.Log;
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -070045import android.util.Pair;
Wei Wang18c76932013-10-29 21:05:37 -070046
Nick Pellybd022f42009-08-14 18:33:38 -070047import java.io.IOException;
Tor Norbye2d497522015-04-23 17:10:21 -070048import java.lang.annotation.Retention;
49import java.lang.annotation.RetentionPolicy;
fredc903ac6f2012-04-24 03:59:57 -070050import java.util.ArrayList;
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -070051import java.util.Arrays;
Nick Pellybd022f42009-08-14 18:33:38 -070052import java.util.Collections;
Matthew Xiecdd94e32013-04-11 16:36:26 -070053import java.util.HashMap;
Wei Wang18c76932013-10-29 21:05:37 -070054import java.util.HashSet;
Wei Wang9fb17912014-07-01 15:10:06 -070055import java.util.List;
Jeff Sharkeyfea17de2013-06-11 14:13:09 -070056import java.util.Locale;
Matthew Xiecdd94e32013-04-11 16:36:26 -070057import java.util.Map;
Nick Pelly24bb9b82009-10-02 20:34:18 -070058import java.util.Set;
Nick Pelly16fb88a2009-10-07 07:44:03 +020059import java.util.UUID;
Adam Lesinski010bf372016-04-11 12:18:18 -070060import java.util.concurrent.TimeoutException;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -070061import java.util.concurrent.locks.ReentrantReadWriteLock;
Nick Pellybd022f42009-08-14 18:33:38 -070062
63/**
Scott Main9fab0ae2009-11-03 18:17:59 -080064 * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
65 * lets you perform fundamental Bluetooth tasks, such as initiate
66 * device discovery, query a list of bonded (paired) devices,
67 * instantiate a {@link BluetoothDevice} using a known MAC address, and create
68 * a {@link BluetoothServerSocket} to listen for connection requests from other
Matthew Xieb30f91e2013-05-29 10:19:06 -070069 * devices, and start a scan for Bluetooth LE devices.
Scott Main9fab0ae2009-11-03 18:17:59 -080070 *
71 * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
Kim Schulz0d376052013-08-22 11:18:02 +020072 * adapter, when running on JELLY_BEAN_MR1 and below, call the
Matthew Xieb30f91e2013-05-29 10:19:06 -070073 * static {@link #getDefaultAdapter} method; when running on JELLY_BEAN_MR2 and
Florian Salbrechter05416af2015-07-31 14:43:15 +010074 * higher, call {@link BluetoothManager#getAdapter}.
Scott Main9fab0ae2009-11-03 18:17:59 -080075 * Fundamentally, this is your starting point for all
76 * Bluetooth actions. Once you have the local adapter, you can get a set of
77 * {@link BluetoothDevice} objects representing all paired devices with
78 * {@link #getBondedDevices()}; start device discovery with
79 * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
80 * listen for incoming connection requests with
Matthew Xieb30f91e2013-05-29 10:19:06 -070081 * {@link #listenUsingRfcommWithServiceRecord(String,UUID)}; or start a scan for
82 * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
Scott Main9fab0ae2009-11-03 18:17:59 -080083 *
Neil Fullerbf0dc0f2015-11-24 18:19:06 +000084 * <p>This class is thread safe.
85 *
Scott Main9fab0ae2009-11-03 18:17:59 -080086 * <p class="note"><strong>Note:</strong>
87 * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
88 * permission and some also require the
89 * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
90 *
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080091 * <div class="special reference">
92 * <h3>Developer Guides</h3>
Hemal Patel65813df2016-08-17 13:18:14 -070093 * <p>
94 * For more information about using Bluetooth, read the <a href=
95 * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
96 * guide.
97 * </p>
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080098 * </div>
99 *
Scott Main9fab0ae2009-11-03 18:17:59 -0800100 * {@see BluetoothDevice}
101 * {@see BluetoothServerSocket}
Nick Pellybd022f42009-08-14 18:33:38 -0700102 */
103public final class BluetoothAdapter {
104 private static final String TAG = "BluetoothAdapter";
fredc0f420372012-04-12 00:02:00 -0700105 private static final boolean DBG = true;
Matthew Xie3b6214f2012-08-29 00:12:29 -0700106 private static final boolean VDBG = false;
Nick Pellybd022f42009-08-14 18:33:38 -0700107
Nick Pellyde893f52009-09-08 13:15:33 -0700108 /**
Svet Ganov408abf72015-05-12 19:13:36 -0700109 * Default MAC address reported to a client that does not have the
110 * android.permission.LOCAL_MAC_ADDRESS permission.
111 *
112 * @hide
113 */
114 public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
115
116 /**
Nick Pellyb24e11b2009-09-08 17:40:43 -0700117 * Sentinel error value for this class. Guaranteed to not equal any other
118 * integer constant in this class. Provided as a convenience for functions
119 * that require a sentinel error value, for example:
120 * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
121 * BluetoothAdapter.ERROR)</code>
122 */
Nick Pelly005b2282009-09-10 10:21:56 -0700123 public static final int ERROR = Integer.MIN_VALUE;
Nick Pellyb24e11b2009-09-08 17:40:43 -0700124
125 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700126 * Broadcast Action: The state of the local Bluetooth adapter has been
127 * changed.
128 * <p>For example, Bluetooth has been turned on or off.
Nick Pelly005b2282009-09-10 10:21:56 -0700129 * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -0700130 * #EXTRA_PREVIOUS_STATE} containing the new and old states
131 * respectively.
132 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
133 */
134 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
135 public static final String ACTION_STATE_CHANGED =
Nick Pelly005b2282009-09-10 10:21:56 -0700136 "android.bluetooth.adapter.action.STATE_CHANGED";
Nick Pellybd022f42009-08-14 18:33:38 -0700137
Nick Pellyde893f52009-09-08 13:15:33 -0700138 /**
139 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
140 * intents to request the current power state. Possible values are:
141 * {@link #STATE_OFF},
142 * {@link #STATE_TURNING_ON},
143 * {@link #STATE_ON},
144 * {@link #STATE_TURNING_OFF},
145 */
146 public static final String EXTRA_STATE =
Nick Pelly005b2282009-09-10 10:21:56 -0700147 "android.bluetooth.adapter.extra.STATE";
Nick Pellyde893f52009-09-08 13:15:33 -0700148 /**
149 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
150 * intents to request the previous power state. Possible values are:
151 * {@link #STATE_OFF},
152 * {@link #STATE_TURNING_ON},
153 * {@link #STATE_ON},
Etan Cohenfd840dd2015-04-23 18:25:08 -0700154 * {@link #STATE_TURNING_OFF}
Nick Pellyde893f52009-09-08 13:15:33 -0700155 */
156 public static final String EXTRA_PREVIOUS_STATE =
Nick Pelly005b2282009-09-10 10:21:56 -0700157 "android.bluetooth.adapter.extra.PREVIOUS_STATE";
Nick Pellybd022f42009-08-14 18:33:38 -0700158
Tor Norbye2d497522015-04-23 17:10:21 -0700159 /** @hide */
160 @IntDef({STATE_OFF, STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, STATE_BLE_TURNING_ON,
161 STATE_BLE_ON, STATE_BLE_TURNING_OFF})
162 @Retention(RetentionPolicy.SOURCE)
163 public @interface AdapterState {}
164
Nick Pellyde893f52009-09-08 13:15:33 -0700165 /**
166 * Indicates the local Bluetooth adapter is off.
167 */
Nick Pelly005b2282009-09-10 10:21:56 -0700168 public static final int STATE_OFF = 10;
Nick Pellyde893f52009-09-08 13:15:33 -0700169 /**
170 * Indicates the local Bluetooth adapter is turning on. However local
171 * clients should wait for {@link #STATE_ON} before attempting to
172 * use the adapter.
173 */
Nick Pelly005b2282009-09-10 10:21:56 -0700174 public static final int STATE_TURNING_ON = 11;
Nick Pellyde893f52009-09-08 13:15:33 -0700175 /**
176 * Indicates the local Bluetooth adapter is on, and ready for use.
177 */
Nick Pelly005b2282009-09-10 10:21:56 -0700178 public static final int STATE_ON = 12;
Nick Pellyde893f52009-09-08 13:15:33 -0700179 /**
180 * Indicates the local Bluetooth adapter is turning off. Local clients
181 * should immediately attempt graceful disconnection of any remote links.
182 */
Nick Pelly005b2282009-09-10 10:21:56 -0700183 public static final int STATE_TURNING_OFF = 13;
Nick Pellyde893f52009-09-08 13:15:33 -0700184
185 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800186 * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on.
187 * @hide
188 */
189 public static final int STATE_BLE_TURNING_ON = 14;
190
191 /**
192 * Indicates the local Bluetooth adapter is in LE only mode.
193 * @hide
194 */
195 public static final int STATE_BLE_ON = 15;
196
197 /**
198 * Indicates the local Bluetooth adapter is turning off LE only mode.
199 * @hide
200 */
201 public static final int STATE_BLE_TURNING_OFF = 16;
202
203 /**
Marie Janssencb21ad72016-12-13 10:51:02 -0800204 * Human-readable string helper for AdapterState
205 * @hide
206 */
207 public static String nameForState(@AdapterState int state) {
208 switch(state) {
209 case STATE_OFF: return "OFF";
210 case STATE_TURNING_ON: return "TURNING_ON";
211 case STATE_ON: return "ON";
212 case STATE_TURNING_OFF: return "TURNING_OFF";
213 case STATE_BLE_TURNING_ON: return "BLE_TURNING_ON";
214 case STATE_BLE_ON: return "BLE_ON";
215 case STATE_BLE_TURNING_OFF: return "BLE_TURNING_OFF";
216 default: return "?!?!? (" + state + ")";
217 }
218 }
219
220 /**
Nick Pelly18b1e792009-09-24 11:14:15 -0700221 * Activity Action: Show a system activity that requests discoverable mode.
Scott Main6d95fc02009-11-19 17:00:19 -0800222 * This activity will also request the user to turn on Bluetooth if it
Nick Pelly1acdcc12009-09-28 10:33:55 -0700223 * is not currently enabled.
Nick Pelly18b1e792009-09-24 11:14:15 -0700224 * <p>Discoverable mode is equivalent to {@link
225 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
226 * this Bluetooth adapter when they perform a discovery.
Scott Main6d95fc02009-11-19 17:00:19 -0800227 * <p>For privacy, Android is not discoverable by default.
228 * <p>The sender of this Intent can optionally use extra field {@link
Nick Pelly18b1e792009-09-24 11:14:15 -0700229 * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
230 * discoverability. Currently the default duration is 120 seconds, and
231 * maximum duration is capped at 300 seconds for each request.
232 * <p>Notification of the result of this activity is posted using the
233 * {@link android.app.Activity#onActivityResult} callback. The
234 * <code>resultCode</code>
Michael Chancdd28642009-11-05 18:29:01 -0800235 * will be the duration (in seconds) of discoverability or
236 * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
237 * discoverability or an error has occurred.
Nick Pelly18b1e792009-09-24 11:14:15 -0700238 * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
Scott Main6d95fc02009-11-19 17:00:19 -0800239 * for global notification whenever the scan mode changes. For example, an
240 * application can be notified when the device has ended discoverability.
Nick Pelly1acdcc12009-09-28 10:33:55 -0700241 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pelly18b1e792009-09-24 11:14:15 -0700242 */
243 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
244 public static final String ACTION_REQUEST_DISCOVERABLE =
245 "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
246
247 /**
248 * Used as an optional int extra field in {@link
249 * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
250 * for discoverability in seconds. The current default is 120 seconds, and
251 * requests over 300 seconds will be capped. These values could change.
252 */
253 public static final String EXTRA_DISCOVERABLE_DURATION =
254 "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
255
256 /**
Nick Pelly1acdcc12009-09-28 10:33:55 -0700257 * Activity Action: Show a system activity that allows the user to turn on
258 * Bluetooth.
259 * <p>This system activity will return once Bluetooth has completed turning
260 * on, or the user has decided not to turn Bluetooth on.
261 * <p>Notification of the result of this activity is posted using the
262 * {@link android.app.Activity#onActivityResult} callback. The
263 * <code>resultCode</code>
Michael Chancdd28642009-11-05 18:29:01 -0800264 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
265 * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
266 * has rejected the request or an error has occurred.
Nick Pelly1acdcc12009-09-28 10:33:55 -0700267 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
268 * for global notification whenever Bluetooth is turned on or off.
269 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
270 */
271 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
272 public static final String ACTION_REQUEST_ENABLE =
273 "android.bluetooth.adapter.action.REQUEST_ENABLE";
274
275 /**
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700276 * Activity Action: Show a system activity that allows the user to turn off
277 * Bluetooth. This is used only if permission review is enabled which is for
278 * apps targeting API less than 23 require a permission review before any of
279 * the app's components can run.
280 * <p>This system activity will return once Bluetooth has completed turning
281 * off, or the user has decided not to turn Bluetooth off.
282 * <p>Notification of the result of this activity is posted using the
283 * {@link android.app.Activity#onActivityResult} callback. The
284 * <code>resultCode</code>
285 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
286 * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
287 * has rejected the request or an error has occurred.
288 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
289 * for global notification whenever Bluetooth is turned on or off.
290 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
291 *
292 * @hide
293 */
294 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
295 public static final String ACTION_REQUEST_DISABLE =
296 "android.bluetooth.adapter.action.REQUEST_DISABLE";
297
298 /**
Wei Wangd91f1932015-03-19 15:09:56 -0700299 * Activity Action: Show a system activity that allows user to enable BLE scans even when
300 * Bluetooth is turned off.<p>
301 *
302 * Notification of result of this activity is posted using
303 * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
304 * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
305 * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
306 * error occurred.
307 *
308 * @hide
309 */
310 @SystemApi
311 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
312 public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
313 "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
314
315 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700316 * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
317 * has changed.
Nick Pelly005b2282009-09-10 10:21:56 -0700318 * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -0700319 * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
320 * respectively.
321 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
322 */
323 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
324 public static final String ACTION_SCAN_MODE_CHANGED =
Nick Pelly005b2282009-09-10 10:21:56 -0700325 "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
Nick Pellyde893f52009-09-08 13:15:33 -0700326
327 /**
328 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
329 * intents to request the current scan mode. Possible values are:
330 * {@link #SCAN_MODE_NONE},
331 * {@link #SCAN_MODE_CONNECTABLE},
332 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
333 */
Nick Pelly005b2282009-09-10 10:21:56 -0700334 public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700335 /**
336 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
337 * intents to request the previous scan mode. Possible values are:
338 * {@link #SCAN_MODE_NONE},
339 * {@link #SCAN_MODE_CONNECTABLE},
340 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
341 */
342 public static final String EXTRA_PREVIOUS_SCAN_MODE =
Nick Pelly005b2282009-09-10 10:21:56 -0700343 "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700344
Tor Norbye2d497522015-04-23 17:10:21 -0700345 /** @hide */
346 @IntDef({SCAN_MODE_NONE, SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE})
347 @Retention(RetentionPolicy.SOURCE)
348 public @interface ScanMode {}
349
Nick Pellyde893f52009-09-08 13:15:33 -0700350 /**
351 * Indicates that both inquiry scan and page scan are disabled on the local
352 * Bluetooth adapter. Therefore this device is neither discoverable
353 * nor connectable from remote Bluetooth devices.
354 */
Nick Pelly005b2282009-09-10 10:21:56 -0700355 public static final int SCAN_MODE_NONE = 20;
Nick Pellyde893f52009-09-08 13:15:33 -0700356 /**
357 * Indicates that inquiry scan is disabled, but page scan is enabled on the
358 * local Bluetooth adapter. Therefore this device is not discoverable from
359 * remote Bluetooth devices, but is connectable from remote devices that
360 * have previously discovered this device.
361 */
Nick Pelly005b2282009-09-10 10:21:56 -0700362 public static final int SCAN_MODE_CONNECTABLE = 21;
Nick Pellyde893f52009-09-08 13:15:33 -0700363 /**
364 * Indicates that both inquiry scan and page scan are enabled on the local
365 * Bluetooth adapter. Therefore this device is both discoverable and
366 * connectable from remote Bluetooth devices.
367 */
Nick Pelly005b2282009-09-10 10:21:56 -0700368 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
Nick Pellybd022f42009-08-14 18:33:38 -0700369
Nick Pelly005b2282009-09-10 10:21:56 -0700370 /**
371 * Broadcast Action: The local Bluetooth adapter has started the remote
372 * device discovery process.
373 * <p>This usually involves an inquiry scan of about 12 seconds, followed
374 * by a page scan of each new device to retrieve its Bluetooth name.
375 * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
376 * remote Bluetooth devices are found.
377 * <p>Device discovery is a heavyweight procedure. New connections to
378 * remote Bluetooth devices should not be attempted while discovery is in
379 * progress, and existing connections will experience limited bandwidth
380 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
381 * discovery.
382 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
383 */
384 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
385 public static final String ACTION_DISCOVERY_STARTED =
386 "android.bluetooth.adapter.action.DISCOVERY_STARTED";
387 /**
388 * Broadcast Action: The local Bluetooth adapter has finished the device
389 * discovery process.
390 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
391 */
392 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
393 public static final String ACTION_DISCOVERY_FINISHED =
394 "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
395
396 /**
397 * Broadcast Action: The local Bluetooth adapter has changed its friendly
398 * Bluetooth name.
399 * <p>This name is visible to remote Bluetooth devices.
400 * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
401 * the name.
402 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
403 */
404 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
405 public static final String ACTION_LOCAL_NAME_CHANGED =
406 "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
407 /**
408 * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
409 * intents to request the local Bluetooth name.
410 */
411 public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
412
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700413 /**
414 * Intent used to broadcast the change in connection state of the local
415 * Bluetooth adapter to a profile of the remote device. When the adapter is
416 * not connected to any profiles of any remote devices and it attempts a
417 * connection to a profile this intent will sent. Once connected, this intent
418 * will not be sent for any more connection attempts to any profiles of any
419 * remote device. When the adapter disconnects from the last profile its
420 * connected to of any remote device, this intent will be sent.
421 *
422 * <p> This intent is useful for applications that are only concerned about
423 * whether the local adapter is connected to any profile of any device and
424 * are not really concerned about which profile. For example, an application
425 * which displays an icon to display whether Bluetooth is connected or not
426 * can use this intent.
427 *
428 * <p>This intent will have 3 extras:
Jaikumar Ganesh0b5b35f2011-02-01 16:47:11 -0800429 * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
430 * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700431 * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
432 *
Jaikumar Ganesh0b5b35f2011-02-01 16:47:11 -0800433 * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
434 * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700435 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
436 *
437 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
438 */
439 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
440 public static final String ACTION_CONNECTION_STATE_CHANGED =
441 "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
442
443 /**
444 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
445 *
446 * This extra represents the current connection state.
447 */
448 public static final String EXTRA_CONNECTION_STATE =
449 "android.bluetooth.adapter.extra.CONNECTION_STATE";
450
451 /**
452 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
453 *
454 * This extra represents the previous connection state.
455 */
456 public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
457 "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
458
Nitin Arorad055adb2015-03-02 15:03:51 -0800459 /**
460 * Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
461 * @hide
462 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700463 @SystemApi
Nitin Arorad055adb2015-03-02 15:03:51 -0800464 public static final String ACTION_BLE_STATE_CHANGED =
tturney1b43e432015-04-29 12:01:00 -0700465 "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800466
467 /**
468 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
469 * by BLE Always on enabled application to know the ACL_CONNECTED event
470 * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection
471 * as Bluetooth LE is the only feature available in STATE_BLE_ON
472 *
473 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which
474 * works in Bluetooth state STATE_ON
475 * @hide
476 */
477 public static final String ACTION_BLE_ACL_CONNECTED =
478 "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";
479
480 /**
481 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
482 * by BLE Always on enabled application to know the ACL_DISCONNECTED event
483 * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth
484 * LE is the only feature available in STATE_BLE_ON
485 *
486 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which
487 * works in Bluetooth state STATE_ON
488 * @hide
489 */
490 public static final String ACTION_BLE_ACL_DISCONNECTED =
491 "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
492
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700493 /** The profile is in disconnected state */
494 public static final int STATE_DISCONNECTED = 0;
495 /** The profile is in connecting state */
496 public static final int STATE_CONNECTING = 1;
497 /** The profile is in connected state */
498 public static final int STATE_CONNECTED = 2;
499 /** The profile is in disconnecting state */
500 public static final int STATE_DISCONNECTING = 3;
501
Nick Pellyf242b7b2009-10-08 00:12:45 +0200502 /** @hide */
fredc0f420372012-04-12 00:02:00 -0700503 public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
Nitin Arorad055adb2015-03-02 15:03:51 -0800504 private final IBinder mToken;
Nick Pellyf242b7b2009-10-08 00:12:45 +0200505
Casper Bonde238e0f92015-04-09 09:24:48 +0200506
507 /** When creating a ServerSocket using listenUsingRfcommOn() or
508 * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create
509 * a ServerSocket that auto assigns a channel number to the first
510 * bluetooth socket.
511 * The channel number assigned to this first Bluetooth Socket will
512 * be stored in the ServerSocket, and reused for subsequent Bluetooth
513 * sockets.
514 * @hide */
515 public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2;
516
517
Nick Pelly005b2282009-09-10 10:21:56 -0700518 private static final int ADDRESS_LENGTH = 17;
Nick Pellybd022f42009-08-14 18:33:38 -0700519
Nick Pellyf242b7b2009-10-08 00:12:45 +0200520 /**
Jake Hambyf51eada2010-09-21 13:39:53 -0700521 * Lazily initialized singleton. Guaranteed final after first object
Nick Pellyf242b7b2009-10-08 00:12:45 +0200522 * constructed.
523 */
524 private static BluetoothAdapter sAdapter;
525
Wei Wangc3059cc2014-07-23 23:34:00 -0700526 private static BluetoothLeScanner sBluetoothLeScanner;
527 private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
528
fredc0f420372012-04-12 00:02:00 -0700529 private final IBluetoothManager mManagerService;
530 private IBluetooth mService;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700531 private final ReentrantReadWriteLock mServiceLock =
532 new ReentrantReadWriteLock();
Nick Pellybd022f42009-08-14 18:33:38 -0700533
Wei Wangf3055892014-03-11 22:22:41 -0700534 private final Object mLock = new Object();
Wei Wangc3059cc2014-07-23 23:34:00 -0700535 private final Map<LeScanCallback, ScanCallback> mLeScanClients;
Matthew Xie484867a2011-08-25 16:45:58 -0700536
Nick Pellybd022f42009-08-14 18:33:38 -0700537 /**
Nick Pellyf242b7b2009-10-08 00:12:45 +0200538 * Get a handle to the default local Bluetooth adapter.
539 * <p>Currently Android only supports one Bluetooth adapter, but the API
540 * could be extended to support more. This will always return the default
541 * adapter.
542 * @return the default local adapter, or null if Bluetooth is not supported
543 * on this hardware platform
544 */
545 public static synchronized BluetoothAdapter getDefaultAdapter() {
546 if (sAdapter == null) {
fredc0f420372012-04-12 00:02:00 -0700547 IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
Nick Pellyf242b7b2009-10-08 00:12:45 +0200548 if (b != null) {
fredc0f420372012-04-12 00:02:00 -0700549 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
550 sAdapter = new BluetoothAdapter(managerService);
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -0800551 } else {
552 Log.e(TAG, "Bluetooth binder is null");
Nick Pellyf242b7b2009-10-08 00:12:45 +0200553 }
554 }
555 return sAdapter;
556 }
557
558 /**
559 * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
Nick Pellybd022f42009-08-14 18:33:38 -0700560 */
fredc0f420372012-04-12 00:02:00 -0700561 BluetoothAdapter(IBluetoothManager managerService) {
562
563 if (managerService == null) {
564 throw new IllegalArgumentException("bluetooth manager service is null");
Nick Pellybd022f42009-08-14 18:33:38 -0700565 }
fredc0f420372012-04-12 00:02:00 -0700566 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700567 mServiceLock.writeLock().lock();
fredc0f420372012-04-12 00:02:00 -0700568 mService = managerService.registerAdapter(mManagerCallback);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700569 } catch (RemoteException e) {
570 Log.e(TAG, "", e);
571 } finally {
572 mServiceLock.writeLock().unlock();
573 }
fredc0f420372012-04-12 00:02:00 -0700574 mManagerService = managerService;
Wei Wangc3059cc2014-07-23 23:34:00 -0700575 mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
Nitin Arorad055adb2015-03-02 15:03:51 -0800576 mToken = new Binder();
Nick Pellybd022f42009-08-14 18:33:38 -0700577 }
578
579 /**
Nick Pelly45e27042009-08-19 11:00:00 -0700580 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
581 * address.
582 * <p>Valid Bluetooth hardware addresses must be upper case, in a format
Nick Pelly005b2282009-09-10 10:21:56 -0700583 * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
584 * available to validate a Bluetooth address.
Nick Pelly45e27042009-08-19 11:00:00 -0700585 * <p>A {@link BluetoothDevice} will always be returned for a valid
586 * hardware address, even if this adapter has never seen that device.
Nick Pellyde893f52009-09-08 13:15:33 -0700587 *
Nick Pellybd022f42009-08-14 18:33:38 -0700588 * @param address valid Bluetooth MAC address
Nick Pelly45e27042009-08-19 11:00:00 -0700589 * @throws IllegalArgumentException if address is invalid
Nick Pellybd022f42009-08-14 18:33:38 -0700590 */
591 public BluetoothDevice getRemoteDevice(String address) {
592 return new BluetoothDevice(address);
593 }
594
595 /**
Nick Pelly75596b42011-12-07 15:03:55 -0800596 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
597 * address.
598 * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
599 * expects the address in network byte order (MSB first).
600 * <p>A {@link BluetoothDevice} will always be returned for a valid
601 * hardware address, even if this adapter has never seen that device.
602 *
603 * @param address Bluetooth MAC address (6 bytes)
604 * @throws IllegalArgumentException if address is invalid
605 */
606 public BluetoothDevice getRemoteDevice(byte[] address) {
607 if (address == null || address.length != 6) {
608 throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
609 }
Jeff Sharkeyfea17de2013-06-11 14:13:09 -0700610 return new BluetoothDevice(String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X",
Nick Pelly75596b42011-12-07 15:03:55 -0800611 address[0], address[1], address[2], address[3], address[4], address[5]));
612 }
613
614 /**
Prerepa Viswanadham248edc32014-10-15 16:36:01 -0700615 * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
616 * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
617 * supported on this device.
Wei Wangc3059cc2014-07-23 23:34:00 -0700618 * <p>
619 * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
620 * on this device before calling this method.
Wei Wangadf6aff2014-05-20 06:30:20 +0000621 */
622 public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
Nitin Arorad055adb2015-03-02 15:03:51 -0800623 if (!getLeAccess()) return null;
Wei Wangc3059cc2014-07-23 23:34:00 -0700624 synchronized(mLock) {
625 if (sBluetoothLeAdvertiser == null) {
626 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
627 }
628 }
629 return sBluetoothLeAdvertiser;
Wei Wangadf6aff2014-05-20 06:30:20 +0000630 }
631
632 /**
633 * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
634 */
635 public BluetoothLeScanner getBluetoothLeScanner() {
Nitin Arorad055adb2015-03-02 15:03:51 -0800636 if (!getLeAccess()) return null;
Wei Wangc3059cc2014-07-23 23:34:00 -0700637 synchronized(mLock) {
638 if (sBluetoothLeScanner == null) {
639 sBluetoothLeScanner = new BluetoothLeScanner(mManagerService);
640 }
641 }
642 return sBluetoothLeScanner;
Wei Wangadf6aff2014-05-20 06:30:20 +0000643 }
644
645 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700646 * Return true if Bluetooth is currently enabled and ready for use.
647 * <p>Equivalent to:
648 * <code>getBluetoothState() == STATE_ON</code>
649 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pellybd022f42009-08-14 18:33:38 -0700650 *
Nick Pellyde893f52009-09-08 13:15:33 -0700651 * @return true if the local adapter is turned on
Nick Pellybd022f42009-08-14 18:33:38 -0700652 */
Tor Norbye2d497522015-04-23 17:10:21 -0700653 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -0700654 public boolean isEnabled() {
655 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700656 mServiceLock.readLock().lock();
657 if (mService != null) return mService.isEnabled();
658 } catch (RemoteException e) {
659 Log.e(TAG, "", e);
660 } finally {
661 mServiceLock.readLock().unlock();
662 }
663
Nick Pellybd022f42009-08-14 18:33:38 -0700664 return false;
665 }
666
667 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800668 * Return true if Bluetooth LE(Always BLE On feature) is currently
669 * enabled and ready for use
670 * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON
671 *
672 * @return true if the local Bluetooth LE adapter is turned on
673 * @hide
674 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700675 @SystemApi
676 public boolean isLeEnabled() {
677 final int state = getLeState();
Marie Janssencb21ad72016-12-13 10:51:02 -0800678 if (DBG) Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
679 return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON);
Nitin Arorad055adb2015-03-02 15:03:51 -0800680 }
681
682 /**
Marie Janssen59804562016-12-28 14:13:21 -0800683 * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
Nitin Arorad055adb2015-03-02 15:03:51 -0800684 *
685 * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
686 * to STATE_OFF and completely shut-down Bluetooth
687 *
688 * <p> If the Adapter state is STATE_ON, This would unregister the existance of
689 * special Bluetooth LE application and hence the further turning off of Bluetooth
690 * from UI would ensure the complete turn-off of Bluetooth rather than staying back
691 * BLE only state
692 *
693 * <p>This is an asynchronous call: it will return immediately, and
694 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
695 * to be notified of subsequent adapter state changes If this call returns
696 * true, then the adapter state will immediately transition from {@link
697 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
698 * later transition to either {@link #STATE_BLE_ON} or {@link
699 * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications
700 * If this call returns false then there was an
701 * immediate problem that will prevent the QAdapter from being turned off -
702 * such as the QAadapter already being turned off.
703 *
704 * @return true to indicate success, or false on
705 * immediate error
706 * @hide
707 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700708 @SystemApi
Nitin Arorad055adb2015-03-02 15:03:51 -0800709 public boolean disableBLE() {
Wei Wang67d84162015-04-26 17:04:29 -0700710 if (!isBleScanAlwaysAvailable()) return false;
Nitin Arorad055adb2015-03-02 15:03:51 -0800711
712 int state = getLeState();
Marie Janssen59804562016-12-28 14:13:21 -0800713 if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) {
714 String packageName = ActivityThread.currentPackageName();
715 if (DBG) Log.d (TAG, "disableBLE(): de-registering " + packageName);
Nitin Arorad055adb2015-03-02 15:03:51 -0800716 try {
Marie Janssen59804562016-12-28 14:13:21 -0800717 mManagerService.updateBleAppCount(mToken, false, packageName);
Nitin Arorad055adb2015-03-02 15:03:51 -0800718 } catch (RemoteException e) {
719 Log.e(TAG, "", e);
720 }
721 return true;
Nitin Arorad055adb2015-03-02 15:03:51 -0800722 }
723
Marie Janssen59804562016-12-28 14:13:21 -0800724 if (DBG) Log.d (TAG, "disableBLE(): Already disabled");
Nitin Arorad055adb2015-03-02 15:03:51 -0800725 return false;
726 }
727
728 /**
Marie Janssen59804562016-12-28 14:13:21 -0800729 * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
Nitin Arorad055adb2015-03-02 15:03:51 -0800730 *
Marie Janssen59804562016-12-28 14:13:21 -0800731 * enableBLE registers the existence of an app using only LE functions.
732 *
733 * enableBLE may enable Bluetooth to an LE only mode so that an app can use
734 * LE related features (BluetoothGatt or BluetoothGattServer classes)
735 *
736 * If the user disables Bluetooth while an app is registered to use LE only features,
737 * Bluetooth will remain on in LE only mode for the app.
738 *
739 * When Bluetooth is in LE only mode, it is not shown as ON to the UI.
740 *
741 * <p>This is an asynchronous call: it returns immediately, and
Nitin Arorad055adb2015-03-02 15:03:51 -0800742 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
Marie Janssen59804562016-12-28 14:13:21 -0800743 * to be notified of adapter state changes.
744 *
745 * If this call returns * true, then the adapter state is either in a mode where
746 * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
747 * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
748 *
749 * If this call returns false then there was an immediate problem that prevents the
750 * adapter from being turned on - such as Airplane mode.
751 *
752 * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
Nitin Arorad055adb2015-03-02 15:03:51 -0800753 * states, It includes all the classic Bluetooth Adapter states along with
754 * internal BLE only states
755 *
Marie Janssen59804562016-12-28 14:13:21 -0800756 * @return true to indicate Bluetooth LE will be available, or false on
Nitin Arorad055adb2015-03-02 15:03:51 -0800757 * immediate error
758 * @hide
759 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700760 @SystemApi
Nitin Arorad055adb2015-03-02 15:03:51 -0800761 public boolean enableBLE() {
Wei Wang67d84162015-04-26 17:04:29 -0700762 if (!isBleScanAlwaysAvailable()) return false;
Nitin Arorad055adb2015-03-02 15:03:51 -0800763
Nitin Arorad055adb2015-03-02 15:03:51 -0800764 try {
Marie Janssen59804562016-12-28 14:13:21 -0800765 String packageName = ActivityThread.currentPackageName();
766 mManagerService.updateBleAppCount(mToken, true, packageName);
Marie Janssen6a383a72016-10-25 10:47:51 -0700767 if (isLeEnabled()) {
768 if (DBG) Log.d(TAG, "enableBLE(): Bluetooth already enabled");
769 return true;
770 }
771 if (DBG) Log.d(TAG, "enableBLE(): Calling enable");
Marie Janssen59804562016-12-28 14:13:21 -0800772 return mManagerService.enable(packageName);
Nitin Arorad055adb2015-03-02 15:03:51 -0800773 } catch (RemoteException e) {
774 Log.e(TAG, "", e);
775 }
776
777 return false;
778 }
779
780 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700781 * Get the current state of the local Bluetooth adapter.
782 * <p>Possible return values are
783 * {@link #STATE_OFF},
784 * {@link #STATE_TURNING_ON},
785 * {@link #STATE_ON},
786 * {@link #STATE_TURNING_OFF}.
787 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pellybd022f42009-08-14 18:33:38 -0700788 *
Nick Pellyde893f52009-09-08 13:15:33 -0700789 * @return current state of Bluetooth adapter
Nick Pellybd022f42009-08-14 18:33:38 -0700790 */
Tor Norbye2d497522015-04-23 17:10:21 -0700791 @RequiresPermission(Manifest.permission.BLUETOOTH)
792 @AdapterState
Nick Pellyde893f52009-09-08 13:15:33 -0700793 public int getState() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700794 int state = BluetoothAdapter.STATE_OFF;
795
Nick Pellybd022f42009-08-14 18:33:38 -0700796 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700797 mServiceLock.readLock().lock();
798 if (mService != null) {
799 state = mService.getState();
fredc0f420372012-04-12 00:02:00 -0700800 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700801 } catch (RemoteException e) {
802 Log.e(TAG, "", e);
803 } finally {
804 mServiceLock.readLock().unlock();
805 }
806
807 // Consider all internal states as OFF
808 if (state == BluetoothAdapter.STATE_BLE_ON
809 || state == BluetoothAdapter.STATE_BLE_TURNING_ON
810 || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -0800811 if (VDBG) Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700812 state = BluetoothAdapter.STATE_OFF;
813 }
Marie Janssencb21ad72016-12-13 10:51:02 -0800814 if (VDBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(state));
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700815 return state;
Nick Pellybd022f42009-08-14 18:33:38 -0700816 }
817
818 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800819 * Get the current state of the local Bluetooth adapter
820 * <p>This returns current internal state of Adapter including LE ON/OFF
821 *
822 * <p>Possible return values are
823 * {@link #STATE_OFF},
824 * {@link #STATE_BLE_TURNING_ON},
825 * {@link #STATE_BLE_ON},
826 * {@link #STATE_TURNING_ON},
827 * {@link #STATE_ON},
828 * {@link #STATE_TURNING_OFF},
829 * {@link #STATE_BLE_TURNING_OFF}.
830 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
831 *
832 * @return current state of Bluetooth adapter
833 * @hide
834 */
Tor Norbye2d497522015-04-23 17:10:21 -0700835 @RequiresPermission(Manifest.permission.BLUETOOTH)
836 @AdapterState
Nitin Arorad055adb2015-03-02 15:03:51 -0800837 public int getLeState() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700838 int state = BluetoothAdapter.STATE_OFF;
839
Nitin Arorad055adb2015-03-02 15:03:51 -0800840 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700841 mServiceLock.readLock().lock();
842 if (mService != null) {
843 state = mService.getState();
Nitin Arorad055adb2015-03-02 15:03:51 -0800844 }
845 } catch (RemoteException e) {
846 Log.e(TAG, "", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700847 } finally {
848 mServiceLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -0800849 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700850
Marie Janssencb21ad72016-12-13 10:51:02 -0800851 if (VDBG) Log.d(TAG,"getLeState() returning " + BluetoothAdapter.nameForState(state));
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700852 return state;
Nitin Arorad055adb2015-03-02 15:03:51 -0800853 }
854
855 boolean getLeAccess() {
Marie Janssencb21ad72016-12-13 10:51:02 -0800856 if (getLeState() == STATE_ON)
Nitin Arorad055adb2015-03-02 15:03:51 -0800857 return true;
858
859 else if (getLeState() == STATE_BLE_ON)
860 return true; // TODO: FILTER SYSTEM APPS HERE <--
861
862 return false;
863 }
864
865 /**
Scott Mained2a70d2009-12-09 16:07:39 -0800866 * Turn on the local Bluetooth adapter&mdash;do not use without explicit
867 * user action to turn on Bluetooth.
Nick Pellyde893f52009-09-08 13:15:33 -0700868 * <p>This powers on the underlying Bluetooth hardware, and starts all
869 * Bluetooth system services.
Scott Mained2a70d2009-12-09 16:07:39 -0800870 * <p class="caution"><strong>Bluetooth should never be enabled without
871 * direct user consent</strong>. If you want to turn on Bluetooth in order
872 * to create a wireless connection, you should use the {@link
873 * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
874 * user permission to turn on Bluetooth. The {@link #enable()} method is
875 * provided only for applications that include a user interface for changing
876 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick3219ab42009-09-25 16:31:39 +0400877 * <p>This is an asynchronous call: it will return immediately, and
Nick Pellyde893f52009-09-08 13:15:33 -0700878 * clients should listen for {@link #ACTION_STATE_CHANGED}
879 * to be notified of subsequent adapter state changes. If this call returns
880 * true, then the adapter state will immediately transition from {@link
881 * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
882 * later transition to either {@link #STATE_OFF} or {@link
883 * #STATE_ON}. If this call returns false then there was an
884 * immediate problem that will prevent the adapter from being turned on -
885 * such as Airplane mode, or the adapter is already turned on.
Scott Mained2a70d2009-12-09 16:07:39 -0800886 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
887 * permission
Nick Pellyde893f52009-09-08 13:15:33 -0700888 *
889 * @return true to indicate adapter startup has begun, or false on
890 * immediate error
Nick Pellybd022f42009-08-14 18:33:38 -0700891 */
Tor Norbye2d497522015-04-23 17:10:21 -0700892 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -0700893 public boolean enable() {
Marie Janssencb21ad72016-12-13 10:51:02 -0800894 if (isEnabled()) {
895 if (DBG) Log.d(TAG, "enable(): BT already enabled!");
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700896 return true;
897 }
Nick Pellybd022f42009-08-14 18:33:38 -0700898 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700899 return mManagerService.enable(ActivityThread.currentPackageName());
Nick Pellybd022f42009-08-14 18:33:38 -0700900 } catch (RemoteException e) {Log.e(TAG, "", e);}
901 return false;
902 }
903
904 /**
Scott Mained2a70d2009-12-09 16:07:39 -0800905 * Turn off the local Bluetooth adapter&mdash;do not use without explicit
906 * user action to turn off Bluetooth.
Nick Pellyde893f52009-09-08 13:15:33 -0700907 * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
908 * system services, and powers down the underlying Bluetooth hardware.
Jake Hambyf51eada2010-09-21 13:39:53 -0700909 * <p class="caution"><strong>Bluetooth should never be disabled without
Scott Mained2a70d2009-12-09 16:07:39 -0800910 * direct user consent</strong>. The {@link #disable()} method is
911 * provided only for applications that include a user interface for changing
912 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick3219ab42009-09-25 16:31:39 +0400913 * <p>This is an asynchronous call: it will return immediately, and
Nick Pellyde893f52009-09-08 13:15:33 -0700914 * clients should listen for {@link #ACTION_STATE_CHANGED}
915 * to be notified of subsequent adapter state changes. If this call returns
916 * true, then the adapter state will immediately transition from {@link
917 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
918 * later transition to either {@link #STATE_OFF} or {@link
919 * #STATE_ON}. If this call returns false then there was an
920 * immediate problem that will prevent the adapter from being turned off -
921 * such as the adapter already being turned off.
Scott Mained2a70d2009-12-09 16:07:39 -0800922 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
923 * permission
Nick Pellybd022f42009-08-14 18:33:38 -0700924 *
Nick Pellyde893f52009-09-08 13:15:33 -0700925 * @return true to indicate adapter shutdown has begun, or false on
926 * immediate error
Nick Pellybd022f42009-08-14 18:33:38 -0700927 */
Tor Norbye2d497522015-04-23 17:10:21 -0700928 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -0700929 public boolean disable() {
930 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700931 return mManagerService.disable(ActivityThread.currentPackageName(), true);
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -0800932 } catch (RemoteException e) {Log.e(TAG, "", e);}
933 return false;
934 }
935
936 /**
937 * Turn off the local Bluetooth adapter and don't persist the setting.
938 *
939 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
940 * permission
941 *
942 * @return true to indicate adapter shutdown has begun, or false on
943 * immediate error
944 * @hide
945 */
946 public boolean disable(boolean persist) {
fredc0f420372012-04-12 00:02:00 -0700947
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -0800948 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700949 return mManagerService.disable(ActivityThread.currentPackageName(), persist);
Nick Pellybd022f42009-08-14 18:33:38 -0700950 } catch (RemoteException e) {Log.e(TAG, "", e);}
951 return false;
952 }
953
Nick Pellyde893f52009-09-08 13:15:33 -0700954 /**
955 * Returns the hardware address of the local Bluetooth adapter.
956 * <p>For example, "00:11:22:AA:BB:CC".
957 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
958 *
959 * @return Bluetooth hardware address as string
960 */
Tor Norbye2d497522015-04-23 17:10:21 -0700961 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -0700962 public String getAddress() {
963 try {
fredc0f420372012-04-12 00:02:00 -0700964 return mManagerService.getAddress();
Nick Pellybd022f42009-08-14 18:33:38 -0700965 } catch (RemoteException e) {Log.e(TAG, "", e);}
966 return null;
967 }
968
969 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700970 * Get the friendly Bluetooth name of the local Bluetooth adapter.
971 * <p>This name is visible to remote Bluetooth devices.
972 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pellybd022f42009-08-14 18:33:38 -0700973 *
Nick Pellyde893f52009-09-08 13:15:33 -0700974 * @return the Bluetooth name, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -0700975 */
976 public String getName() {
977 try {
fredc116d1d462012-04-20 14:47:08 -0700978 return mManagerService.getName();
Nick Pellybd022f42009-08-14 18:33:38 -0700979 } catch (RemoteException e) {Log.e(TAG, "", e);}
980 return null;
981 }
982
983 /**
Zhihai Xuaf5971e2013-06-10 20:28:31 -0700984 * enable or disable Bluetooth HCI snoop log.
985 *
986 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
987 * permission
988 *
989 * @return true to indicate configure HCI log successfully, or false on
990 * immediate error
991 * @hide
992 */
993 public boolean configHciSnoopLog(boolean enable) {
994 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700995 mServiceLock.readLock().lock();
996 if (mService != null) return mService.configHciSnoopLog(enable);
997 } catch (RemoteException e) {
998 Log.e(TAG, "", e);
999 } finally {
1000 mServiceLock.readLock().unlock();
1001 }
Zhihai Xuaf5971e2013-06-10 20:28:31 -07001002 return false;
1003 }
1004
1005 /**
Ajay Panickercda6e872015-07-28 16:52:09 -07001006 * Factory reset bluetooth settings.
1007 *
1008 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
1009 * permission
1010 *
1011 * @return true to indicate that the config file was successfully cleared
1012 *
1013 * @hide
1014 */
1015 public boolean factoryReset() {
1016 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001017 mServiceLock.readLock().lock();
Ajay Panickercda6e872015-07-28 16:52:09 -07001018 if (mService != null) {
1019 return mService.factoryReset();
1020 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001021 SystemProperties.set("persist.bluetooth.factoryreset", "true");
1022 } catch (RemoteException e) {
1023 Log.e(TAG, "", e);
1024 } finally {
1025 mServiceLock.readLock().unlock();
1026 }
Ajay Panickercda6e872015-07-28 16:52:09 -07001027 return false;
1028 }
1029
1030 /**
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001031 * Get the UUIDs supported by the local Bluetooth adapter.
1032 *
1033 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1034 *
1035 * @return the UUIDs supported by the local Bluetooth Adapter.
1036 * @hide
1037 */
1038 public ParcelUuid[] getUuids() {
Matthew Xie44b58ab2011-11-16 12:27:57 -08001039 if (getState() != STATE_ON) return null;
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001040 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001041 mServiceLock.readLock().lock();
1042 if (mService != null) return mService.getUuids();
1043 } catch (RemoteException e) {
1044 Log.e(TAG, "", e);
1045 } finally {
1046 mServiceLock.readLock().unlock();
1047 }
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001048 return null;
1049 }
1050
1051 /**
Jake Hamby0f584302010-09-16 18:12:51 -07001052 * Set the friendly Bluetooth name of the local Bluetooth adapter.
Nick Pellyde893f52009-09-08 13:15:33 -07001053 * <p>This name is visible to remote Bluetooth devices.
Jake Hamby0f584302010-09-16 18:12:51 -07001054 * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
1055 * encoding, although many remote devices can only display the first
1056 * 40 characters, and some may be limited to just 20.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001057 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1058 * will return false. After turning on Bluetooth,
1059 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1060 * to get the updated value.
Nick Pellyde893f52009-09-08 13:15:33 -07001061 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
Nick Pellybd022f42009-08-14 18:33:38 -07001062 *
Nick Pellyde893f52009-09-08 13:15:33 -07001063 * @param name a valid Bluetooth name
1064 * @return true if the name was set, false otherwise
Nick Pellybd022f42009-08-14 18:33:38 -07001065 */
Tor Norbye2d497522015-04-23 17:10:21 -07001066 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001067 public boolean setName(String name) {
Jaikumar Ganeshf5ff1702010-08-06 19:03:13 -07001068 if (getState() != STATE_ON) return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001069 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001070 mServiceLock.readLock().lock();
1071 if (mService != null) return mService.setName(name);
1072 } catch (RemoteException e) {
1073 Log.e(TAG, "", e);
1074 } finally {
1075 mServiceLock.readLock().unlock();
1076 }
Nick Pellybd022f42009-08-14 18:33:38 -07001077 return false;
1078 }
1079
1080 /**
Jake Hamby0f584302010-09-16 18:12:51 -07001081 * Get the current Bluetooth scan mode of the local Bluetooth adapter.
Nick Pellyde893f52009-09-08 13:15:33 -07001082 * <p>The Bluetooth scan mode determines if the local adapter is
1083 * connectable and/or discoverable from remote Bluetooth devices.
1084 * <p>Possible values are:
1085 * {@link #SCAN_MODE_NONE},
1086 * {@link #SCAN_MODE_CONNECTABLE},
1087 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001088 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1089 * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
1090 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1091 * to get the updated value.
Nick Pellyde893f52009-09-08 13:15:33 -07001092 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1093 *
1094 * @return scan mode
Nick Pellybd022f42009-08-14 18:33:38 -07001095 */
Tor Norbye2d497522015-04-23 17:10:21 -07001096 @RequiresPermission(Manifest.permission.BLUETOOTH)
1097 @ScanMode
Nick Pellybd022f42009-08-14 18:33:38 -07001098 public int getScanMode() {
Jaikumar Ganeshf5ff1702010-08-06 19:03:13 -07001099 if (getState() != STATE_ON) return SCAN_MODE_NONE;
Nick Pellybd022f42009-08-14 18:33:38 -07001100 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001101 mServiceLock.readLock().lock();
1102 if (mService != null) return mService.getScanMode();
1103 } catch (RemoteException e) {
1104 Log.e(TAG, "", e);
1105 } finally {
1106 mServiceLock.readLock().unlock();
1107 }
Nick Pellyde893f52009-09-08 13:15:33 -07001108 return SCAN_MODE_NONE;
Nick Pellybd022f42009-08-14 18:33:38 -07001109 }
1110
1111 /**
Nick Pellyde893f52009-09-08 13:15:33 -07001112 * Set the Bluetooth scan mode of the local Bluetooth adapter.
1113 * <p>The Bluetooth scan mode determines if the local adapter is
1114 * connectable and/or discoverable from remote Bluetooth devices.
Nick Pelly12835472009-09-25 15:00:29 -07001115 * <p>For privacy reasons, discoverable mode is automatically turned off
1116 * after <code>duration</code> seconds. For example, 120 seconds should be
1117 * enough for a remote device to initiate and complete its discovery
1118 * process.
Nick Pellyde893f52009-09-08 13:15:33 -07001119 * <p>Valid scan mode values are:
1120 * {@link #SCAN_MODE_NONE},
1121 * {@link #SCAN_MODE_CONNECTABLE},
1122 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001123 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1124 * will return false. After turning on Bluetooth,
1125 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1126 * to get the updated value.
Nick Pelly18b1e792009-09-24 11:14:15 -07001127 * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}
1128 * <p>Applications cannot set the scan mode. They should use
1129 * <code>startActivityForResult(
1130 * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
1131 * </code>instead.
Nick Pellyde893f52009-09-08 13:15:33 -07001132 *
1133 * @param mode valid scan mode
Nick Pelly12835472009-09-25 15:00:29 -07001134 * @param duration time in seconds to apply scan mode, only used for
1135 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
Nick Pellyde893f52009-09-08 13:15:33 -07001136 * @return true if the scan mode was set, false otherwise
Nick Pelly18b1e792009-09-24 11:14:15 -07001137 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07001138 */
Tor Norbye2d497522015-04-23 17:10:21 -07001139 public boolean setScanMode(@ScanMode int mode, int duration) {
Jaikumar Ganeshf5ff1702010-08-06 19:03:13 -07001140 if (getState() != STATE_ON) return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001141 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001142 mServiceLock.readLock().lock();
1143 if (mService != null) return mService.setScanMode(mode, duration);
1144 } catch (RemoteException e) {
1145 Log.e(TAG, "", e);
1146 } finally {
1147 mServiceLock.readLock().unlock();
1148 }
Nick Pellyde893f52009-09-08 13:15:33 -07001149 return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001150 }
1151
Nick Pelly45e27042009-08-19 11:00:00 -07001152 /** @hide */
Nick Pelly12835472009-09-25 15:00:29 -07001153 public boolean setScanMode(int mode) {
Jaikumar Ganeshf5ff1702010-08-06 19:03:13 -07001154 if (getState() != STATE_ON) return false;
Srikanth Uppala827de2d2012-04-04 03:33:26 -07001155 /* getDiscoverableTimeout() to use the latest from NV than use 0 */
1156 return setScanMode(mode, getDiscoverableTimeout());
Nick Pelly12835472009-09-25 15:00:29 -07001157 }
1158
1159 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -07001160 public int getDiscoverableTimeout() {
Jaikumar Ganeshf5ff1702010-08-06 19:03:13 -07001161 if (getState() != STATE_ON) return -1;
Nick Pellybd022f42009-08-14 18:33:38 -07001162 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001163 mServiceLock.readLock().lock();
1164 if (mService != null) return mService.getDiscoverableTimeout();
1165 } catch (RemoteException e) {
1166 Log.e(TAG, "", e);
1167 } finally {
1168 mServiceLock.readLock().unlock();
1169 }
Nick Pellybd022f42009-08-14 18:33:38 -07001170 return -1;
1171 }
1172
Nick Pelly45e27042009-08-19 11:00:00 -07001173 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -07001174 public void setDiscoverableTimeout(int timeout) {
Jaikumar Ganeshf5ff1702010-08-06 19:03:13 -07001175 if (getState() != STATE_ON) return;
Nick Pellybd022f42009-08-14 18:33:38 -07001176 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001177 mServiceLock.readLock().lock();
1178 if (mService != null) mService.setDiscoverableTimeout(timeout);
1179 } catch (RemoteException e) {
1180 Log.e(TAG, "", e);
1181 } finally {
1182 mServiceLock.readLock().unlock();
1183 }
Nick Pellybd022f42009-08-14 18:33:38 -07001184 }
1185
Nick Pelly005b2282009-09-10 10:21:56 -07001186 /**
1187 * Start the remote device discovery process.
1188 * <p>The discovery process usually involves an inquiry scan of about 12
1189 * seconds, followed by a page scan of each new device to retrieve its
1190 * Bluetooth name.
1191 * <p>This is an asynchronous call, it will return immediately. Register
1192 * for {@link #ACTION_DISCOVERY_STARTED} and {@link
1193 * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
1194 * discovery starts and completes. Register for {@link
1195 * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
1196 * are found.
1197 * <p>Device discovery is a heavyweight procedure. New connections to
1198 * remote Bluetooth devices should not be attempted while discovery is in
1199 * progress, and existing connections will experience limited bandwidth
1200 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
Scott Main6d95fc02009-11-19 17:00:19 -08001201 * discovery. Discovery is not managed by the Activity,
1202 * but is run as a system service, so an application should always call
1203 * {@link BluetoothAdapter#cancelDiscovery()} even if it
1204 * did not directly request a discovery, just to be sure.
Nick Pelly005b2282009-09-10 10:21:56 -07001205 * <p>Device discovery will only find remote devices that are currently
1206 * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
1207 * not discoverable by default, and need to be entered into a special mode.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001208 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1209 * will return false. After turning on Bluetooth,
1210 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1211 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001212 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
1213 *
1214 * @return true on success, false on error
1215 */
Tor Norbye2d497522015-04-23 17:10:21 -07001216 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001217 public boolean startDiscovery() {
Jaikumar Ganeshf5ff1702010-08-06 19:03:13 -07001218 if (getState() != STATE_ON) return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001219 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001220 mServiceLock.readLock().lock();
1221 if (mService != null) return mService.startDiscovery();
1222 } catch (RemoteException e) {
1223 Log.e(TAG, "", e);
1224 } finally {
1225 mServiceLock.readLock().unlock();
1226 }
Nick Pellybd022f42009-08-14 18:33:38 -07001227 return false;
1228 }
1229
Nick Pelly005b2282009-09-10 10:21:56 -07001230 /**
1231 * Cancel the current device discovery process.
1232 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
Jake Hamby0f584302010-09-16 18:12:51 -07001233 * <p>Because discovery is a heavyweight procedure for the Bluetooth
Scott Main6d95fc02009-11-19 17:00:19 -08001234 * adapter, this method should always be called before attempting to connect
1235 * to a remote device with {@link
1236 * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
1237 * the Activity, but is run as a system service, so an application should
1238 * always call cancel discovery even if it did not directly request a
1239 * discovery, just to be sure.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001240 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1241 * will return false. After turning on Bluetooth,
1242 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1243 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001244 *
1245 * @return true on success, false on error
1246 */
Tor Norbye2d497522015-04-23 17:10:21 -07001247 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pelly005b2282009-09-10 10:21:56 -07001248 public boolean cancelDiscovery() {
Jaikumar Ganeshf5ff1702010-08-06 19:03:13 -07001249 if (getState() != STATE_ON) return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001250 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001251 mServiceLock.readLock().lock();
1252 if (mService != null) return mService.cancelDiscovery();
1253 } catch (RemoteException e) {
1254 Log.e(TAG, "", e);
1255 } finally {
1256 mServiceLock.readLock().unlock();
1257 }
Nick Pelly005b2282009-09-10 10:21:56 -07001258 return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001259 }
1260
Nick Pelly005b2282009-09-10 10:21:56 -07001261 /**
1262 * Return true if the local Bluetooth adapter is currently in the device
1263 * discovery process.
1264 * <p>Device discovery is a heavyweight procedure. New connections to
1265 * remote Bluetooth devices should not be attempted while discovery is in
1266 * progress, and existing connections will experience limited bandwidth
1267 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1268 * discovery.
1269 * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
1270 * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
1271 * starts or completes.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001272 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1273 * will return false. After turning on Bluetooth,
1274 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1275 * to get the updated value.
Nick Pellye6ee3be2009-10-08 23:27:28 +02001276 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
Nick Pelly005b2282009-09-10 10:21:56 -07001277 *
1278 * @return true if discovering
1279 */
Tor Norbye2d497522015-04-23 17:10:21 -07001280 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07001281 public boolean isDiscovering() {
Jaikumar Ganeshf5ff1702010-08-06 19:03:13 -07001282 if (getState() != STATE_ON) return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001283 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001284 mServiceLock.readLock().lock();
1285 if (mService != null) return mService.isDiscovering();
1286 } catch (RemoteException e) {
1287 Log.e(TAG, "", e);
1288 } finally {
1289 mServiceLock.readLock().unlock();
1290 }
Nick Pellybd022f42009-08-14 18:33:38 -07001291 return false;
1292 }
1293
1294 /**
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001295 * Return true if the multi advertisement is supported by the chipset
1296 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001297 * @return true if Multiple Advertisement feature is supported
1298 */
1299 public boolean isMultipleAdvertisementSupported() {
1300 if (getState() != STATE_ON) return false;
1301 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001302 mServiceLock.readLock().lock();
1303 if (mService != null) return mService.isMultiAdvertisementSupported();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001304 } catch (RemoteException e) {
1305 Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001306 } finally {
1307 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001308 }
1309 return false;
1310 }
1311
1312 /**
Wei Wangd91f1932015-03-19 15:09:56 -07001313 * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
1314 *
1315 * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
1316 * fetch scan results even when Bluetooth is turned off.<p>
1317 *
1318 * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
1319 *
1320 * @hide
1321 */
1322 @SystemApi
1323 public boolean isBleScanAlwaysAvailable() {
Wei Wang67d84162015-04-26 17:04:29 -07001324 try {
1325 return mManagerService.isBleScanAlwaysAvailable();
1326 } catch (RemoteException e) {
1327 Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e);
1328 return false;
1329 }
Wei Wangd91f1932015-03-19 15:09:56 -07001330 }
1331
1332 /**
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001333 * Return true if offloaded filters are supported
1334 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001335 * @return true if chipset supports on-chip filtering
1336 */
1337 public boolean isOffloadedFilteringSupported() {
Wei Wang46ab7232015-05-07 16:25:33 -07001338 if (!getLeAccess()) return false;
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001339 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001340 mServiceLock.readLock().lock();
1341 if (mService != null) return mService.isOffloadedFilteringSupported();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001342 } catch (RemoteException e) {
1343 Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001344 } finally {
1345 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001346 }
1347 return false;
1348 }
1349
1350 /**
1351 * Return true if offloaded scan batching is supported
1352 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001353 * @return true if chipset supports on-chip scan batching
1354 */
1355 public boolean isOffloadedScanBatchingSupported() {
Wei Wang46ab7232015-05-07 16:25:33 -07001356 if (!getLeAccess()) return false;
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001357 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001358 mServiceLock.readLock().lock();
1359 if (mService != null) return mService.isOffloadedScanBatchingSupported();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001360 } catch (RemoteException e) {
1361 Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001362 } finally {
1363 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001364 }
1365 return false;
1366 }
1367
1368 /**
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001369 * Return true if hardware has entries available for matching beacons
1370 *
1371 * @return true if there are hw entries available for matching beacons
1372 * @hide
1373 */
1374 public boolean isHardwareTrackingFiltersAvailable() {
Wei Wang46ab7232015-05-07 16:25:33 -07001375 if (!getLeAccess()) return false;
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001376 try {
Prerepa Viswanadhamdb1dbb82015-04-09 17:14:50 -07001377 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
1378 if (iGatt == null) {
1379 // BLE is not supported
1380 return false;
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001381 }
Prerepa Viswanadhamdb1dbb82015-04-09 17:14:50 -07001382 return (iGatt.numHwTrackFiltersAvailable() != 0);
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001383 } catch (RemoteException e) {
1384 Log.e(TAG, "", e);
1385 }
1386 return false;
1387 }
1388
1389 /**
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001390 * Return the record of {@link BluetoothActivityEnergyInfo} object that
1391 * has the activity and energy info. This can be used to ascertain what
1392 * the controller has been up to, since the last sample.
1393 * @param updateType Type of info, cached vs refreshed.
1394 *
1395 * @return a record with {@link BluetoothActivityEnergyInfo} or null if
1396 * report is unavailable or unsupported
Adam Lesinski010bf372016-04-11 12:18:18 -07001397 * @deprecated use the asynchronous
Adam Lesinski991357f2016-05-10 14:00:03 -07001398 * {@link #requestControllerActivityEnergyInfo(ResultReceiver)} instead.
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001399 * @hide
1400 */
Adam Lesinski010bf372016-04-11 12:18:18 -07001401 @Deprecated
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001402 public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001403 SynchronousResultReceiver receiver = new SynchronousResultReceiver();
Adam Lesinski991357f2016-05-10 14:00:03 -07001404 requestControllerActivityEnergyInfo(receiver);
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001405 try {
Adam Lesinski010bf372016-04-11 12:18:18 -07001406 SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
1407 if (result.bundle != null) {
1408 return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
1409 }
1410 } catch (TimeoutException e) {
1411 Log.e(TAG, "getControllerActivityEnergyInfo timed out");
1412 }
1413 return null;
1414 }
1415
1416 /**
1417 * Request the record of {@link BluetoothActivityEnergyInfo} object that
1418 * has the activity and energy info. This can be used to ascertain what
1419 * the controller has been up to, since the last sample.
1420 *
1421 * A null value for the activity info object may be sent if the bluetooth service is
1422 * unreachable or the device does not support reporting such information.
1423 *
Adam Lesinski010bf372016-04-11 12:18:18 -07001424 * @param result The callback to which to send the activity info.
1425 * @hide
1426 */
Adam Lesinski991357f2016-05-10 14:00:03 -07001427 public void requestControllerActivityEnergyInfo(ResultReceiver result) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001428 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001429 mServiceLock.readLock().lock();
1430 if (mService != null) {
1431 mService.requestActivityInfo(result);
1432 result = null;
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001433 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001434 } catch (RemoteException e) {
1435 Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
Adam Lesinski991357f2016-05-10 14:00:03 -07001436 } finally {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001437 mServiceLock.readLock().unlock();
Adam Lesinski991357f2016-05-10 14:00:03 -07001438 if (result != null) {
1439 // Only send an immediate result if we failed.
1440 result.send(0, null);
1441 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001442 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001443 }
1444
1445 /**
Nick Pelly005b2282009-09-10 10:21:56 -07001446 * Return the set of {@link BluetoothDevice} objects that are bonded
1447 * (paired) to the local adapter.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001448 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1449 * will return an empty set. After turning on Bluetooth,
1450 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1451 * to get the updated value.
Nick Pellye6ee3be2009-10-08 23:27:28 +02001452 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
Nick Pellybd022f42009-08-14 18:33:38 -07001453 *
Nick Pelly005b2282009-09-10 10:21:56 -07001454 * @return unmodifiable set of {@link BluetoothDevice}, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -07001455 */
Tor Norbye2d497522015-04-23 17:10:21 -07001456 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07001457 public Set<BluetoothDevice> getBondedDevices() {
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001458 if (getState() != STATE_ON) {
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -08001459 return toDeviceSet(new BluetoothDevice[0]);
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001460 }
Nick Pellybd022f42009-08-14 18:33:38 -07001461 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001462 mServiceLock.readLock().lock();
1463 if (mService != null) return toDeviceSet(mService.getBondedDevices());
fredc0f420372012-04-12 00:02:00 -07001464 return toDeviceSet(new BluetoothDevice[0]);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001465 } catch (RemoteException e) {
1466 Log.e(TAG, "", e);
1467 } finally {
1468 mServiceLock.readLock().unlock();
1469 }
Nick Pellybd022f42009-08-14 18:33:38 -07001470 return null;
1471 }
1472
1473 /**
Bryce Leeb1301fa2016-10-09 12:54:42 -07001474 * Gets the currently supported profiles by the adapter.
1475 *
1476 *<p> This can be used to check whether a profile is supported before attempting
1477 * to connect to its respective proxy.
1478 *
1479 * @return a list of integers indicating the ids of supported profiles as defined in
1480 * {@link BluetoothProfile}.
1481 * @hide
1482 */
1483 public List<Integer> getSupportedProfiles() {
1484 final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
1485
1486 try {
1487 synchronized (mManagerCallback) {
1488 if (mService != null) {
1489 final long supportedProfilesBitMask = mService.getSupportedProfiles();
1490
1491 for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
1492 if ((supportedProfilesBitMask & (1 << i)) != 0) {
1493 supportedProfiles.add(i);
1494 }
1495 }
1496 }
1497 }
Marie Janssencb21ad72016-12-13 10:51:02 -08001498 } catch (RemoteException e) {
1499 Log.e(TAG, "getSupportedProfiles:", e);
1500 }
Bryce Leeb1301fa2016-10-09 12:54:42 -07001501 return supportedProfiles;
1502 }
1503
1504 /**
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07001505 * Get the current connection state of the local Bluetooth adapter.
1506 * This can be used to check whether the local Bluetooth adapter is connected
1507 * to any profile of any other remote Bluetooth Device.
1508 *
1509 * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
1510 * intent to get the connection state of the adapter.
1511 *
1512 * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED},
1513 * {@link #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
1514 *
1515 * @hide
1516 */
1517 public int getConnectionState() {
1518 if (getState() != STATE_ON) return BluetoothAdapter.STATE_DISCONNECTED;
1519 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001520 mServiceLock.readLock().lock();
1521 if (mService != null) return mService.getAdapterConnectionState();
1522 } catch (RemoteException e) {
1523 Log.e(TAG, "getConnectionState:", e);
1524 } finally {
1525 mServiceLock.readLock().unlock();
1526 }
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07001527 return BluetoothAdapter.STATE_DISCONNECTED;
1528 }
1529
1530 /**
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07001531 * Get the current connection state of a profile.
1532 * This function can be used to check whether the local Bluetooth adapter
1533 * is connected to any remote device for a specific profile.
Scott Main2d68a6b2011-09-26 22:59:38 -07001534 * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
Jaikumar Ganesh93547902011-08-23 12:21:55 -07001535 * {@link BluetoothProfile#A2DP}.
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07001536 *
1537 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
1538 *
1539 * <p> Return value can be one of
Jaikumar Ganesh93547902011-08-23 12:21:55 -07001540 * {@link BluetoothProfile#STATE_DISCONNECTED},
1541 * {@link BluetoothProfile#STATE_CONNECTING},
1542 * {@link BluetoothProfile#STATE_CONNECTED},
1543 * {@link BluetoothProfile#STATE_DISCONNECTING}
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07001544 */
Tor Norbye2d497522015-04-23 17:10:21 -07001545 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07001546 public int getProfileConnectionState(int profile) {
1547 if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED;
1548 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001549 mServiceLock.readLock().lock();
1550 if (mService != null) return mService.getProfileConnectionState(profile);
Jaikumar Ganesh93547902011-08-23 12:21:55 -07001551 } catch (RemoteException e) {
1552 Log.e(TAG, "getProfileConnectionState:", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001553 } finally {
1554 mServiceLock.readLock().unlock();
Jaikumar Ganesh93547902011-08-23 12:21:55 -07001555 }
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07001556 return BluetoothProfile.STATE_DISCONNECTED;
1557 }
1558
1559 /**
Nick Pelly45e27042009-08-19 11:00:00 -07001560 * Create a listening, secure RFCOMM Bluetooth socket.
1561 * <p>A remote device connecting to this socket will be authenticated and
Nick Pellybd022f42009-08-14 18:33:38 -07001562 * communication on this socket will be encrypted.
Nick Pelly45e27042009-08-19 11:00:00 -07001563 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
Nick Pelly24bb9b82009-10-02 20:34:18 -07001564 * connections from a listening {@link BluetoothServerSocket}.
Nick Pelly45e27042009-08-19 11:00:00 -07001565 * <p>Valid RFCOMM channels are in range 1 to 30.
Nick Pelly24bb9b82009-10-02 20:34:18 -07001566 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
Nick Pelly45e27042009-08-19 11:00:00 -07001567 * @param channel RFCOMM channel to listen on
1568 * @return a listening RFCOMM BluetoothServerSocket
1569 * @throws IOException on error, for example Bluetooth not available, or
1570 * insufficient permissions, or channel in use.
Nick Pelly24bb9b82009-10-02 20:34:18 -07001571 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07001572 */
Nick Pelly45e27042009-08-19 11:00:00 -07001573 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02001574 return listenUsingRfcommOn(channel, false, false);
Casper Bonde23284232015-04-21 13:12:05 +02001575 }
1576
1577 /**
1578 * Create a listening, secure RFCOMM Bluetooth socket.
1579 * <p>A remote device connecting to this socket will be authenticated and
1580 * communication on this socket will be encrypted.
1581 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1582 * connections from a listening {@link BluetoothServerSocket}.
1583 * <p>Valid RFCOMM channels are in range 1 to 30.
1584 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1585 * <p>To auto assign a channel without creating a SDP record use
1586 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
1587 * @param channel RFCOMM channel to listen on
1588 * @param mitm enforce man-in-the-middle protection for authentication.
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02001589 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 connections.
Casper Bonde23284232015-04-21 13:12:05 +02001590 * @return a listening RFCOMM BluetoothServerSocket
1591 * @throws IOException on error, for example Bluetooth not available, or
1592 * insufficient permissions, or channel in use.
1593 * @hide
1594 */
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02001595 public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
1596 boolean min16DigitPin)
1597 throws IOException {
Nick Pellybd022f42009-08-14 18:33:38 -07001598 BluetoothServerSocket socket = new BluetoothServerSocket(
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02001599 BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm, min16DigitPin);
Nick Pelly24bb9b82009-10-02 20:34:18 -07001600 int errno = socket.mSocket.bindListen();
Casper Bonde23284232015-04-21 13:12:05 +02001601 if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02001602 socket.setChannel(socket.mSocket.getPort());
1603 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07001604 if (errno != 0) {
zzy3b147b72012-04-03 19:48:32 -07001605 //TODO(BT): Throw the same exception error code
1606 // that the previous code was using.
1607 //socket.mSocket.throwErrnoNative(errno);
1608 throw new IOException("Error: " + errno);
Nick Pellybd022f42009-08-14 18:33:38 -07001609 }
1610 return socket;
1611 }
1612
1613 /**
Nick Pelly24bb9b82009-10-02 20:34:18 -07001614 * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
1615 * <p>A remote device connecting to this socket will be authenticated and
1616 * communication on this socket will be encrypted.
1617 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1618 * connections from a listening {@link BluetoothServerSocket}.
1619 * <p>The system will assign an unused RFCOMM channel to listen on.
1620 * <p>The system will also register a Service Discovery
1621 * Protocol (SDP) record with the local SDP server containing the specified
1622 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1623 * can use the same UUID to query our SDP server and discover which channel
1624 * to connect to. This SDP record will be removed when this socket is
1625 * closed, or if this application closes unexpectedly.
Nick Pelly16fb88a2009-10-07 07:44:03 +02001626 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1627 * connect to this socket from another device using the same {@link UUID}.
Nick Pelly24bb9b82009-10-02 20:34:18 -07001628 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1629 * @param name service name for SDP record
1630 * @param uuid uuid for SDP record
1631 * @return a listening RFCOMM BluetoothServerSocket
1632 * @throws IOException on error, for example Bluetooth not available, or
1633 * insufficient permissions, or channel in use.
1634 */
Tor Norbye2d497522015-04-23 17:10:21 -07001635 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pelly16fb88a2009-10-07 07:44:03 +02001636 public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
Nick Pelly24bb9b82009-10-02 20:34:18 -07001637 throws IOException {
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08001638 return createNewRfcommSocketAndRecord(name, uuid, true, true);
1639 }
1640
1641 /**
1642 * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01001643 * <p>The link key is not required to be authenticated, i.e the communication may be
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08001644 * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices,
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01001645 * the link will be encrypted, as encryption is mandartory.
1646 * For legacy devices (pre Bluetooth 2.1 devices) the link will not
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08001647 * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
1648 * encrypted and authenticated communication channel is desired.
1649 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1650 * connections from a listening {@link BluetoothServerSocket}.
1651 * <p>The system will assign an unused RFCOMM channel to listen on.
1652 * <p>The system will also register a Service Discovery
1653 * Protocol (SDP) record with the local SDP server containing the specified
1654 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1655 * can use the same UUID to query our SDP server and discover which channel
1656 * to connect to. This SDP record will be removed when this socket is
1657 * closed, or if this application closes unexpectedly.
1658 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1659 * connect to this socket from another device using the same {@link UUID}.
1660 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1661 * @param name service name for SDP record
1662 * @param uuid uuid for SDP record
1663 * @return a listening RFCOMM BluetoothServerSocket
1664 * @throws IOException on error, for example Bluetooth not available, or
1665 * insufficient permissions, or channel in use.
1666 */
Tor Norbye2d497522015-04-23 17:10:21 -07001667 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08001668 public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
1669 throws IOException {
1670 return createNewRfcommSocketAndRecord(name, uuid, false, false);
1671 }
1672
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01001673 /**
1674 * Create a listening, encrypted,
1675 * RFCOMM Bluetooth socket with Service Record.
1676 * <p>The link will be encrypted, but the link key is not required to be authenticated
1677 * i.e the communication is vulnerable to Man In the Middle attacks. Use
1678 * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
1679 * <p> Use this socket if authentication of link key is not possible.
1680 * For example, for Bluetooth 2.1 devices, if any of the devices does not have
1681 * an input and output capability or just has the ability to display a numeric key,
1682 * a secure socket connection is not possible and this socket can be used.
1683 * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
1684 * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
1685 * For more details, refer to the Security Model section 5.2 (vol 3) of
1686 * Bluetooth Core Specification version 2.1 + EDR.
1687 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1688 * connections from a listening {@link BluetoothServerSocket}.
1689 * <p>The system will assign an unused RFCOMM channel to listen on.
1690 * <p>The system will also register a Service Discovery
1691 * Protocol (SDP) record with the local SDP server containing the specified
1692 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1693 * can use the same UUID to query our SDP server and discover which channel
1694 * to connect to. This SDP record will be removed when this socket is
1695 * closed, or if this application closes unexpectedly.
1696 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1697 * connect to this socket from another device using the same {@link UUID}.
1698 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1699 * @param name service name for SDP record
1700 * @param uuid uuid for SDP record
1701 * @return a listening RFCOMM BluetoothServerSocket
1702 * @throws IOException on error, for example Bluetooth not available, or
1703 * insufficient permissions, or channel in use.
1704 * @hide
1705 */
1706 public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(
1707 String name, UUID uuid) throws IOException {
1708 return createNewRfcommSocketAndRecord(name, uuid, false, true);
1709 }
1710
zzy3b147b72012-04-03 19:48:32 -07001711
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08001712 private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
1713 boolean auth, boolean encrypt) throws IOException {
Nick Pelly24bb9b82009-10-02 20:34:18 -07001714 BluetoothServerSocket socket;
zzy3b147b72012-04-03 19:48:32 -07001715 socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth,
1716 encrypt, new ParcelUuid(uuid));
1717 socket.setServiceName(name);
1718 int errno = socket.mSocket.bindListen();
1719 if (errno != 0) {
1720 //TODO(BT): Throw the same exception error code
1721 // that the previous code was using.
1722 //socket.mSocket.throwErrnoNative(errno);
1723 throw new IOException("Error: " + errno);
Nick Pelly24bb9b82009-10-02 20:34:18 -07001724 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07001725 return socket;
1726 }
1727
1728 /**
Nick Pellybd022f42009-08-14 18:33:38 -07001729 * Construct an unencrypted, unauthenticated, RFCOMM server socket.
1730 * Call #accept to retrieve connections to this socket.
1731 * @return An RFCOMM BluetoothServerSocket
1732 * @throws IOException On error, for example Bluetooth not available, or
1733 * insufficient permissions.
Nick Pelly45e27042009-08-19 11:00:00 -07001734 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07001735 */
1736 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
1737 BluetoothServerSocket socket = new BluetoothServerSocket(
1738 BluetoothSocket.TYPE_RFCOMM, false, false, port);
Nick Pelly24bb9b82009-10-02 20:34:18 -07001739 int errno = socket.mSocket.bindListen();
Casper Bonde238e0f92015-04-09 09:24:48 +02001740 if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1741 socket.setChannel(socket.mSocket.getPort());
1742 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07001743 if (errno != 0) {
zzy3b147b72012-04-03 19:48:32 -07001744 //TODO(BT): Throw the same exception error code
1745 // that the previous code was using.
1746 //socket.mSocket.throwErrnoNative(errno);
1747 throw new IOException("Error: " + errno);
Nick Pellybd022f42009-08-14 18:33:38 -07001748 }
1749 return socket;
1750 }
1751
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01001752 /**
1753 * Construct an encrypted, RFCOMM server socket.
1754 * Call #accept to retrieve connections to this socket.
1755 * @return An RFCOMM BluetoothServerSocket
1756 * @throws IOException On error, for example Bluetooth not available, or
1757 * insufficient permissions.
1758 * @hide
1759 */
1760 public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port)
1761 throws IOException {
1762 BluetoothServerSocket socket = new BluetoothServerSocket(
1763 BluetoothSocket.TYPE_RFCOMM, false, true, port);
1764 int errno = socket.mSocket.bindListen();
Casper Bonde238e0f92015-04-09 09:24:48 +02001765 if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1766 socket.setChannel(socket.mSocket.getPort());
1767 }
zzy3b147b72012-04-03 19:48:32 -07001768 if (errno < 0) {
1769 //TODO(BT): Throw the same exception error code
1770 // that the previous code was using.
1771 //socket.mSocket.throwErrnoNative(errno);
1772 throw new IOException("Error: " + errno);
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01001773 }
1774 return socket;
1775 }
1776
Nick Pellybd022f42009-08-14 18:33:38 -07001777 /**
1778 * Construct a SCO server socket.
1779 * Call #accept to retrieve connections to this socket.
1780 * @return A SCO BluetoothServerSocket
1781 * @throws IOException On error, for example Bluetooth not available, or
1782 * insufficient permissions.
Nick Pelly45e27042009-08-19 11:00:00 -07001783 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07001784 */
1785 public static BluetoothServerSocket listenUsingScoOn() throws IOException {
1786 BluetoothServerSocket socket = new BluetoothServerSocket(
1787 BluetoothSocket.TYPE_SCO, false, false, -1);
Nick Pelly24bb9b82009-10-02 20:34:18 -07001788 int errno = socket.mSocket.bindListen();
zzy3b147b72012-04-03 19:48:32 -07001789 if (errno < 0) {
1790 //TODO(BT): Throw the same exception error code
1791 // that the previous code was using.
1792 //socket.mSocket.throwErrnoNative(errno);
Nick Pellybd022f42009-08-14 18:33:38 -07001793 }
1794 return socket;
1795 }
1796
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07001797 /**
Casper Bonde238e0f92015-04-09 09:24:48 +02001798 * Construct an encrypted, authenticated, L2CAP server socket.
1799 * Call #accept to retrieve connections to this socket.
Casper Bonde23284232015-04-21 13:12:05 +02001800 * <p>To auto assign a port without creating a SDP record use
1801 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
1802 * @param port the PSM to listen on
1803 * @param mitm enforce man-in-the-middle protection for authentication.
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02001804 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 connections.
Casper Bonde238e0f92015-04-09 09:24:48 +02001805 * @return An L2CAP BluetoothServerSocket
1806 * @throws IOException On error, for example Bluetooth not available, or
1807 * insufficient permissions.
1808 * @hide
1809 */
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02001810 public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
1811 throws IOException {
Casper Bonde238e0f92015-04-09 09:24:48 +02001812 BluetoothServerSocket socket = new BluetoothServerSocket(
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02001813 BluetoothSocket.TYPE_L2CAP, true, true, port, mitm, min16DigitPin);
Casper Bonde238e0f92015-04-09 09:24:48 +02001814 int errno = socket.mSocket.bindListen();
1815 if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1816 socket.setChannel(socket.mSocket.getPort());
1817 }
1818 if (errno != 0) {
1819 //TODO(BT): Throw the same exception error code
1820 // that the previous code was using.
1821 //socket.mSocket.throwErrnoNative(errno);
1822 throw new IOException("Error: " + errno);
1823 }
1824 return socket;
1825 }
1826
1827 /**
Casper Bonde23284232015-04-21 13:12:05 +02001828 * Construct an encrypted, authenticated, L2CAP server socket.
1829 * Call #accept to retrieve connections to this socket.
1830 * <p>To auto assign a port without creating a SDP record use
1831 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
1832 * @param port the PSM to listen on
1833 * @return An L2CAP BluetoothServerSocket
1834 * @throws IOException On error, for example Bluetooth not available, or
1835 * insufficient permissions.
1836 * @hide
1837 */
1838 public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02001839 return listenUsingL2capOn(port, false, false);
Casper Bonde23284232015-04-21 13:12:05 +02001840 }
1841
1842 /**
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07001843 * Read the local Out of Band Pairing Data
1844 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1845 *
1846 * @return Pair<byte[], byte[]> of Hash and Randomizer
1847 *
1848 * @hide
1849 */
1850 public Pair<byte[], byte[]> readOutOfBandData() {
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07001851 return null;
1852 }
1853
Scott Main299ae672011-01-19 21:13:18 -08001854 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07001855 * Get the profile proxy object associated with the profile.
1856 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001857 * <p>Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
Matthew Xieddf7e472013-03-01 18:41:02 -08001858 * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, or
1859 * {@link BluetoothProfile#GATT_SERVER}. Clients must implement
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07001860 * {@link BluetoothProfile.ServiceListener} to get notified of
1861 * the connection status and to get the proxy object.
1862 *
1863 * @param context Context of the application
1864 * @param listener The service Listener for connection callbacks.
Scott Main2d68a6b2011-09-26 22:59:38 -07001865 * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH},
Andre Eisenbachab258132015-05-04 13:28:04 -07001866 * {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}.
1867 * {@link BluetoothProfile#GATT} or {@link BluetoothProfile#GATT_SERVER}.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07001868 * @return true on success, false on error
1869 */
1870 public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
1871 int profile) {
1872 if (context == null || listener == null) return false;
1873
1874 if (profile == BluetoothProfile.HEADSET) {
1875 BluetoothHeadset headset = new BluetoothHeadset(context, listener);
1876 return true;
1877 } else if (profile == BluetoothProfile.A2DP) {
1878 BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
1879 return true;
Mike Lockwood2263dd12014-05-14 09:51:30 -07001880 } else if (profile == BluetoothProfile.A2DP_SINK) {
1881 BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
1882 return true;
Mike Lockwood94b59de2014-06-02 16:20:37 -07001883 } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
1884 BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
1885 return true;
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -08001886 } else if (profile == BluetoothProfile.INPUT_DEVICE) {
1887 BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
1888 return true;
Jaikumar Ganesh74ef1192011-02-23 10:22:15 -08001889 } else if (profile == BluetoothProfile.PAN) {
1890 BluetoothPan pan = new BluetoothPan(context, listener);
1891 return true;
Jaikumar Ganesh2ea1e852011-04-01 16:33:09 -07001892 } else if (profile == BluetoothProfile.HEALTH) {
1893 BluetoothHealth health = new BluetoothHealth(context, listener);
1894 return true;
Kim Schulz0d376052013-08-22 11:18:02 +02001895 } else if (profile == BluetoothProfile.MAP) {
1896 BluetoothMap map = new BluetoothMap(context, listener);
1897 return true;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07001898 } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
1899 BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
Hemant Gupta7aca90f2013-08-19 19:03:51 +05301900 return true;
Casper Bonde2a5f6082015-03-19 10:36:45 +01001901 } else if (profile == BluetoothProfile.SAP) {
1902 BluetoothSap sap = new BluetoothSap(context, listener);
1903 return true;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08001904 } else if (profile == BluetoothProfile.PBAP_CLIENT) {
1905 BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
1906 return true;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07001907 } else if (profile == BluetoothProfile.MAP_CLIENT) {
1908 BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
1909 return true;
Ivan Podogov5297dba2016-12-30 14:35:09 +00001910 } else if (profile == BluetoothProfile.INPUT_HOST) {
1911 BluetoothInputHost iHost = new BluetoothInputHost(context, listener);
1912 return true;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07001913 } else {
1914 return false;
1915 }
1916 }
1917
1918 /**
1919 * Close the connection of the profile proxy to the Service.
1920 *
1921 * <p> Clients should call this when they are no longer using
1922 * the proxy obtained from {@link #getProfileProxy}.
Scott Main2d68a6b2011-09-26 22:59:38 -07001923 * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET} or
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07001924 * {@link BluetoothProfile#A2DP}
1925 *
1926 * @param profile
1927 * @param proxy Profile proxy object
1928 */
1929 public void closeProfileProxy(int profile, BluetoothProfile proxy) {
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08001930 if (proxy == null) return;
1931
1932 switch (profile) {
1933 case BluetoothProfile.HEADSET:
1934 BluetoothHeadset headset = (BluetoothHeadset)proxy;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07001935 headset.close();
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08001936 break;
1937 case BluetoothProfile.A2DP:
1938 BluetoothA2dp a2dp = (BluetoothA2dp)proxy;
1939 a2dp.close();
1940 break;
Mike Lockwood2263dd12014-05-14 09:51:30 -07001941 case BluetoothProfile.A2DP_SINK:
1942 BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink)proxy;
1943 a2dpSink.close();
1944 break;
Mike Lockwood94b59de2014-06-02 16:20:37 -07001945 case BluetoothProfile.AVRCP_CONTROLLER:
1946 BluetoothAvrcpController avrcp = (BluetoothAvrcpController)proxy;
1947 avrcp.close();
1948 break;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08001949 case BluetoothProfile.INPUT_DEVICE:
1950 BluetoothInputDevice iDev = (BluetoothInputDevice)proxy;
1951 iDev.close();
1952 break;
1953 case BluetoothProfile.PAN:
1954 BluetoothPan pan = (BluetoothPan)proxy;
1955 pan.close();
1956 break;
1957 case BluetoothProfile.HEALTH:
1958 BluetoothHealth health = (BluetoothHealth)proxy;
1959 health.close();
1960 break;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001961 case BluetoothProfile.GATT:
1962 BluetoothGatt gatt = (BluetoothGatt)proxy;
1963 gatt.close();
1964 break;
1965 case BluetoothProfile.GATT_SERVER:
1966 BluetoothGattServer gattServer = (BluetoothGattServer)proxy;
1967 gattServer.close();
1968 break;
Kim Schulz0d376052013-08-22 11:18:02 +02001969 case BluetoothProfile.MAP:
1970 BluetoothMap map = (BluetoothMap)proxy;
1971 map.close();
1972 break;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07001973 case BluetoothProfile.HEADSET_CLIENT:
1974 BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient)proxy;
1975 headsetClient.close();
Hemant Gupta7aca90f2013-08-19 19:03:51 +05301976 break;
Casper Bonde2a5f6082015-03-19 10:36:45 +01001977 case BluetoothProfile.SAP:
1978 BluetoothSap sap = (BluetoothSap)proxy;
1979 sap.close();
1980 break;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08001981 case BluetoothProfile.PBAP_CLIENT:
1982 BluetoothPbapClient pbapClient = (BluetoothPbapClient)proxy;
1983 pbapClient.close();
1984 break;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07001985 case BluetoothProfile.MAP_CLIENT:
1986 BluetoothMapClient mapClient = (BluetoothMapClient)proxy;
1987 mapClient.close();
1988 break;
Ivan Podogov5297dba2016-12-30 14:35:09 +00001989 case BluetoothProfile.INPUT_HOST:
1990 BluetoothInputHost iHost = (BluetoothInputHost) proxy;
1991 iHost.close();
1992 break;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07001993 }
1994 }
1995
fredc0f420372012-04-12 00:02:00 -07001996 final private IBluetoothManagerCallback mManagerCallback =
1997 new IBluetoothManagerCallback.Stub() {
1998 public void onBluetoothServiceUp(IBluetooth bluetoothService) {
Marie Janssen9fa24912016-10-18 10:04:24 -07001999 if (DBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002000
2001 mServiceLock.writeLock().lock();
2002 mService = bluetoothService;
2003 mServiceLock.writeLock().unlock();
2004
2005 synchronized (mProxyServiceStateCallbacks) {
2006 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ) {
2007 try {
2008 if (cb != null) {
2009 cb.onBluetoothServiceUp(bluetoothService);
2010 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08002011 Log.d(TAG, "onBluetoothServiceUp: cb is null!");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002012 }
2013 } catch (Exception e) {
2014 Log.e(TAG,"",e);
Matthew Xie60675b22015-02-06 14:09:54 -08002015 }
fredc903ac6f2012-04-24 03:59:57 -07002016 }
fredc0f420372012-04-12 00:02:00 -07002017 }
2018 }
2019
2020 public void onBluetoothServiceDown() {
Marie Janssen9fa24912016-10-18 10:04:24 -07002021 if (DBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002022
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002023 try {
2024 mServiceLock.writeLock().lock();
2025 mService = null;
2026 if (mLeScanClients != null) mLeScanClients.clear();
2027 if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup();
2028 if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup();
2029 } finally {
2030 mServiceLock.writeLock().unlock();
2031 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002032
2033 synchronized (mProxyServiceStateCallbacks) {
2034 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
2035 try {
2036 if (cb != null) {
2037 cb.onBluetoothServiceDown();
2038 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08002039 Log.d(TAG, "onBluetoothServiceDown: cb is null!");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002040 }
2041 } catch (Exception e) {
2042 Log.e(TAG,"",e);
Matthew Xie60675b22015-02-06 14:09:54 -08002043 }
fredc903ac6f2012-04-24 03:59:57 -07002044 }
fredc0f420372012-04-12 00:02:00 -07002045 }
2046 }
Nitin Arorad055adb2015-03-02 15:03:51 -08002047
2048 public void onBrEdrDown() {
Marie Janssencb21ad72016-12-13 10:51:02 -08002049 if (VDBG) Log.i(TAG, "onBrEdrDown: " + mService);
Nitin Arorad055adb2015-03-02 15:03:51 -08002050 }
fredc0f420372012-04-12 00:02:00 -07002051 };
2052
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002053 /**
Martijn Coenen6c614b72012-04-18 13:01:15 -07002054 * Enable the Bluetooth Adapter, but don't auto-connect devices
2055 * and don't persist state. Only for use by system applications.
2056 * @hide
2057 */
2058 public boolean enableNoAutoConnect() {
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002059 if (isEnabled() == true){
Marie Janssencb21ad72016-12-13 10:51:02 -08002060 if (DBG) Log.d(TAG, "enableNoAutoConnect(): BT already enabled!");
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002061 return true;
2062 }
2063 try {
Marie Janssen59804562016-12-28 14:13:21 -08002064 return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName());
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002065 } catch (RemoteException e) {Log.e(TAG, "", e);}
2066 return false;
Martijn Coenen6c614b72012-04-18 13:01:15 -07002067 }
2068
2069 /**
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002070 * Enable control of the Bluetooth Adapter for a single application.
2071 *
2072 * <p>Some applications need to use Bluetooth for short periods of time to
2073 * transfer data but don't want all the associated implications like
2074 * automatic connection to headsets etc.
2075 *
2076 * <p> Multiple applications can call this. This is reference counted and
2077 * Bluetooth disabled only when no one else is using it. There will be no UI
2078 * shown to the user while bluetooth is being enabled. Any user action will
2079 * override this call. For example, if user wants Bluetooth on and the last
2080 * user of this API wanted to disable Bluetooth, Bluetooth will not be
2081 * turned off.
2082 *
2083 * <p> This API is only meant to be used by internal applications. Third
2084 * party applications but use {@link #enable} and {@link #disable} APIs.
2085 *
2086 * <p> If this API returns true, it means the callback will be called.
2087 * The callback will be called with the current state of Bluetooth.
2088 * If the state is not what was requested, an internal error would be the
Jaikumar Ganeshf5fb6c82011-08-03 14:17:22 -07002089 * reason. If Bluetooth is already on and if this function is called to turn
2090 * it on, the api will return true and a callback will be called.
2091 *
2092 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002093 *
2094 * @param on True for on, false for off.
2095 * @param callback The callback to notify changes to the state.
2096 * @hide
2097 */
2098 public boolean changeApplicationBluetoothState(boolean on,
2099 BluetoothStateChangeCallback callback) {
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002100 return false;
2101 }
2102
2103 /**
2104 * @hide
2105 */
2106 public interface BluetoothStateChangeCallback {
2107 public void onBluetoothStateChange(boolean on);
2108 }
2109
2110 /**
2111 * @hide
2112 */
2113 public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
2114 private BluetoothStateChangeCallback mCallback;
2115
2116 StateChangeCallbackWrapper(BluetoothStateChangeCallback
2117 callback) {
2118 mCallback = callback;
2119 }
2120
2121 @Override
2122 public void onBluetoothStateChange(boolean on) {
2123 mCallback.onBluetoothStateChange(on);
2124 }
2125 }
2126
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -08002127 private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
2128 Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
2129 return Collections.unmodifiableSet(deviceSet);
Nick Pellybd022f42009-08-14 18:33:38 -07002130 }
Nick Pelly005b2282009-09-10 10:21:56 -07002131
fredc0f420372012-04-12 00:02:00 -07002132 protected void finalize() throws Throwable {
2133 try {
2134 mManagerService.unregisterAdapter(mManagerCallback);
2135 } catch (RemoteException e) {
2136 Log.e(TAG, "", e);
2137 } finally {
2138 super.finalize();
2139 }
2140 }
2141
2142
Nick Pelly005b2282009-09-10 10:21:56 -07002143 /**
Nick Pelly75596b42011-12-07 15:03:55 -08002144 * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
Nick Pelly55e66f12009-09-18 11:37:06 -07002145 * <p>Alphabetic characters must be uppercase to be valid.
Nick Pelly005b2282009-09-10 10:21:56 -07002146 *
2147 * @param address Bluetooth address as string
2148 * @return true if the address is valid, false otherwise
2149 */
2150 public static boolean checkBluetoothAddress(String address) {
2151 if (address == null || address.length() != ADDRESS_LENGTH) {
2152 return false;
2153 }
2154 for (int i = 0; i < ADDRESS_LENGTH; i++) {
2155 char c = address.charAt(i);
2156 switch (i % 3) {
2157 case 0:
2158 case 1:
Nick Pelly55e66f12009-09-18 11:37:06 -07002159 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
2160 // hex character, OK
2161 break;
Nick Pelly005b2282009-09-10 10:21:56 -07002162 }
2163 return false;
2164 case 2:
2165 if (c == ':') {
2166 break; // OK
2167 }
2168 return false;
2169 }
2170 }
2171 return true;
2172 }
fredc0f420372012-04-12 00:02:00 -07002173
2174 /*package*/ IBluetoothManager getBluetoothManager() {
2175 return mManagerService;
2176 }
2177
Matthew Xie60675b22015-02-06 14:09:54 -08002178 final private ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = new ArrayList<IBluetoothManagerCallback>();
fredcd6883532012-04-25 17:46:13 -07002179
fredc903ac6f2012-04-24 03:59:57 -07002180 /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
Matthew Xie60675b22015-02-06 14:09:54 -08002181 synchronized (mProxyServiceStateCallbacks) {
fredcd6883532012-04-25 17:46:13 -07002182 if (cb == null) {
fredcbf072a72012-05-09 16:52:50 -07002183 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
2184 } else if (!mProxyServiceStateCallbacks.contains(cb)) {
2185 mProxyServiceStateCallbacks.add(cb);
fredc903ac6f2012-04-24 03:59:57 -07002186 }
2187 }
2188 return mService;
2189 }
2190
2191 /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
Matthew Xie60675b22015-02-06 14:09:54 -08002192 synchronized (mProxyServiceStateCallbacks) {
fredcbf072a72012-05-09 16:52:50 -07002193 mProxyServiceStateCallbacks.remove(cb);
fredc0f420372012-04-12 00:02:00 -07002194 }
2195 }
Matthew Xieddf7e472013-03-01 18:41:02 -08002196
2197 /**
Matthew Xiecdd94e32013-04-11 16:36:26 -07002198 * Callback interface used to deliver LE scan results.
Matthew Xieddf7e472013-03-01 18:41:02 -08002199 *
Matthew Xiecdd94e32013-04-11 16:36:26 -07002200 * @see #startLeScan(LeScanCallback)
2201 * @see #startLeScan(UUID[], LeScanCallback)
Matthew Xieddf7e472013-03-01 18:41:02 -08002202 */
Matthew Xiecdd94e32013-04-11 16:36:26 -07002203 public interface LeScanCallback {
2204 /**
2205 * Callback reporting an LE device found during a device scan initiated
2206 * by the {@link BluetoothAdapter#startLeScan} function.
2207 *
2208 * @param device Identifies the remote device
2209 * @param rssi The RSSI value for the remote device as reported by the
2210 * Bluetooth hardware. 0 if no RSSI value is available.
2211 * @param scanRecord The content of the advertisement record offered by
2212 * the remote device.
2213 */
2214 public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
Matthew Xieddf7e472013-03-01 18:41:02 -08002215 }
2216
2217 /**
2218 * Starts a scan for Bluetooth LE devices.
2219 *
2220 * <p>Results of the scan are reported using the
Matthew Xiecdd94e32013-04-11 16:36:26 -07002221 * {@link LeScanCallback#onLeScan} callback.
Matthew Xieddf7e472013-03-01 18:41:02 -08002222 *
Matthew Xied5752332013-04-24 17:51:37 -07002223 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
Matthew Xieddf7e472013-03-01 18:41:02 -08002224 *
Matthew Xiecdd94e32013-04-11 16:36:26 -07002225 * @param callback the callback LE scan results are delivered
Matthew Xieddf7e472013-03-01 18:41:02 -08002226 * @return true, if the scan was started successfully
Wei Wangaf74e662014-07-09 14:03:42 -07002227 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
2228 * instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08002229 */
Wei Wangaf74e662014-07-09 14:03:42 -07002230 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07002231 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xiecdd94e32013-04-11 16:36:26 -07002232 public boolean startLeScan(LeScanCallback callback) {
2233 return startLeScan(null, callback);
Matthew Xieddf7e472013-03-01 18:41:02 -08002234 }
2235
2236 /**
2237 * Starts a scan for Bluetooth LE devices, looking for devices that
2238 * advertise given services.
2239 *
2240 * <p>Devices which advertise all specified services are reported using the
Matthew Xiecdd94e32013-04-11 16:36:26 -07002241 * {@link LeScanCallback#onLeScan} callback.
Matthew Xieddf7e472013-03-01 18:41:02 -08002242 *
Matthew Xied5752332013-04-24 17:51:37 -07002243 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
Matthew Xieddf7e472013-03-01 18:41:02 -08002244 *
2245 * @param serviceUuids Array of services to look for
Matthew Xiecdd94e32013-04-11 16:36:26 -07002246 * @param callback the callback LE scan results are delivered
Matthew Xieddf7e472013-03-01 18:41:02 -08002247 * @return true, if the scan was started successfully
Wei Wangaf74e662014-07-09 14:03:42 -07002248 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
2249 * instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08002250 */
Wei Wangaf74e662014-07-09 14:03:42 -07002251 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07002252 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Wei Wangc3059cc2014-07-23 23:34:00 -07002253 public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
Andreas Gampee6748ce2015-12-11 18:00:38 -08002254 if (DBG) Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
Matthew Xiecdd94e32013-04-11 16:36:26 -07002255 if (callback == null) {
2256 if (DBG) Log.e(TAG, "startLeScan: null callback");
Matthew Xieddf7e472013-03-01 18:41:02 -08002257 return false;
2258 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002259 BluetoothLeScanner scanner = getBluetoothLeScanner();
2260 if (scanner == null) {
2261 if (DBG) Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
2262 return false;
2263 }
Matthew Xieddf7e472013-03-01 18:41:02 -08002264
Matthew Xiecdd94e32013-04-11 16:36:26 -07002265 synchronized(mLeScanClients) {
2266 if (mLeScanClients.containsKey(callback)) {
2267 if (DBG) Log.e(TAG, "LE Scan has already started");
2268 return false;
2269 }
2270
2271 try {
2272 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
Matthew Xie32ab77b2013-05-08 19:26:57 -07002273 if (iGatt == null) {
2274 // BLE is not supported
2275 return false;
2276 }
2277
Wei Wangc3059cc2014-07-23 23:34:00 -07002278 ScanCallback scanCallback = new ScanCallback() {
2279 @Override
2280 public void onScanResult(int callbackType, ScanResult result) {
2281 if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
2282 // Should not happen.
2283 Log.e(TAG, "LE Scan has already started");
2284 return;
2285 }
2286 ScanRecord scanRecord = result.getScanRecord();
2287 if (scanRecord == null) {
2288 return;
2289 }
2290 if (serviceUuids != null) {
2291 List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
2292 for (UUID uuid : serviceUuids) {
2293 uuids.add(new ParcelUuid(uuid));
2294 }
2295 List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
2296 if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
2297 if (DBG) Log.d(TAG, "uuids does not match");
2298 return;
2299 }
2300 }
2301 callback.onLeScan(result.getDevice(), result.getRssi(),
2302 scanRecord.getBytes());
2303 }
2304 };
2305 ScanSettings settings = new ScanSettings.Builder()
2306 .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
2307 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
2308
2309 List<ScanFilter> filters = new ArrayList<ScanFilter>();
2310 if (serviceUuids != null && serviceUuids.length > 0) {
2311 // Note scan filter does not support matching an UUID array so we put one
2312 // UUID to hardware and match the whole array in callback.
2313 ScanFilter filter = new ScanFilter.Builder().setServiceUuid(
2314 new ParcelUuid(serviceUuids[0])).build();
2315 filters.add(filter);
Matthew Xiecdd94e32013-04-11 16:36:26 -07002316 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002317 scanner.startScan(filters, settings, scanCallback);
2318
2319 mLeScanClients.put(callback, scanCallback);
2320 return true;
2321
Matthew Xiecdd94e32013-04-11 16:36:26 -07002322 } catch (RemoteException e) {
2323 Log.e(TAG,"",e);
2324 }
2325 }
2326 return false;
Matthew Xieddf7e472013-03-01 18:41:02 -08002327 }
2328
2329 /**
2330 * Stops an ongoing Bluetooth LE device scan.
2331 *
Matthew Xied5752332013-04-24 17:51:37 -07002332 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
Matthew Xiecdd94e32013-04-11 16:36:26 -07002333 *
2334 * @param callback used to identify which scan to stop
2335 * must be the same handle used to start the scan
Wei Wangaf74e662014-07-09 14:03:42 -07002336 * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08002337 */
Wei Wangaf74e662014-07-09 14:03:42 -07002338 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07002339 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xiecdd94e32013-04-11 16:36:26 -07002340 public void stopLeScan(LeScanCallback callback) {
2341 if (DBG) Log.d(TAG, "stopLeScan()");
Wei Wangc3059cc2014-07-23 23:34:00 -07002342 BluetoothLeScanner scanner = getBluetoothLeScanner();
2343 if (scanner == null) {
2344 return;
Matthew Xieddf7e472013-03-01 18:41:02 -08002345 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002346 synchronized (mLeScanClients) {
2347 ScanCallback scanCallback = mLeScanClients.remove(callback);
2348 if (scanCallback == null) {
2349 if (DBG) Log.d(TAG, "scan not started yet");
2350 return;
Matthew Xieddf7e472013-03-01 18:41:02 -08002351 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002352 scanner.stopScan(scanCallback);
Prerepa Viswanadham8f2e74c2014-07-09 12:51:59 -07002353 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07002354 }
Nick Pellybd022f42009-08-14 18:33:38 -07002355}