blob: 17ae9078ef982c824688b416ff75081a3bc8f29c [file] [log] [blame]
Nick Pelly2d664882009-08-14 18:33:38 -07001/*
Joseph Pirozzo6f56b0f2016-03-04 13:02:54 -08002 * Copyright (C) 2009-2016 The Android Open Source Project
Casper Bondec0a7c932015-04-09 09:24:48 +02003 * Copyright (C) 2015 Samsung LSI
Nick Pelly2d664882009-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 Norbye27ce6cf2015-04-23 17:10:21 -070020import android.Manifest;
21import android.annotation.IntDef;
22import android.annotation.RequiresPermission;
Nick Pelly7482a802009-09-08 13:15:33 -070023import android.annotation.SdkConstant;
24import android.annotation.SdkConstant.SdkConstantType;
Wei Wang43c66e22015-03-19 15:09:56 -070025import android.annotation.SystemApi;
Svetoslav Ganov5682fb82016-06-29 17:31:44 -070026import android.app.ActivityThread;
Wei Wang7df2e522014-05-22 12:10:25 -070027import android.bluetooth.le.BluetoothLeAdvertiser;
28import android.bluetooth.le.BluetoothLeScanner;
Jakub Pawlowskib74a8cd2017-01-16 07:21:01 -080029import android.bluetooth.le.PeriodicAdvertisingManager;
Wei Wang7faed2f2014-07-09 14:03:42 -070030import android.bluetooth.le.ScanCallback;
Wei Wang4c2da322014-07-23 23:34:00 -070031import android.bluetooth.le.ScanFilter;
32import android.bluetooth.le.ScanRecord;
Wei Wang7dbe2ac2014-07-01 15:10:06 -070033import android.bluetooth.le.ScanResult;
Wei Wang7faed2f2014-07-09 14:03:42 -070034import android.bluetooth.le.ScanSettings;
Jaikumar Ganesh2af07762010-08-24 17:36:13 -070035import android.content.Context;
Adam Lesinski6b31ff82016-04-11 12:18:18 -070036import android.os.BatteryStats;
Wei Wangbaa2d7c2015-05-07 16:25:33 -070037import android.os.Binder;
Nick Pelly79b3ff82009-10-08 00:12:45 +020038import android.os.IBinder;
Nick Pelly03759e52009-09-28 12:33:17 -070039import android.os.ParcelUuid;
Nick Pelly2d664882009-08-14 18:33:38 -070040import android.os.RemoteException;
Adam Lesinski6b31ff82016-04-11 12:18:18 -070041import android.os.ResultReceiver;
Nick Pelly79b3ff82009-10-08 00:12:45 +020042import android.os.ServiceManager;
Adam Lesinski6b31ff82016-04-11 12:18:18 -070043import android.os.SynchronousResultReceiver;
Ajay Panicker75f3ec22016-02-29 16:09:14 -080044import android.os.SystemProperties;
Nick Pelly2d664882009-08-14 18:33:38 -070045import android.util.Log;
Jaikumar Ganesh76965ca2010-09-09 15:37:57 -070046import android.util.Pair;
Wei Wang2f7544c2013-10-29 21:05:37 -070047
Nick Pelly2d664882009-08-14 18:33:38 -070048import java.io.IOException;
Tor Norbye27ce6cf2015-04-23 17:10:21 -070049import java.lang.annotation.Retention;
50import java.lang.annotation.RetentionPolicy;
fredcf1f5dde2012-04-24 03:59:57 -070051import java.util.ArrayList;
Jaikumar Ganesh76965ca2010-09-09 15:37:57 -070052import java.util.Arrays;
Nick Pelly2d664882009-08-14 18:33:38 -070053import java.util.Collections;
Matthew Xie01e8e2a2013-04-11 16:36:26 -070054import java.util.HashMap;
Wei Wang2f7544c2013-10-29 21:05:37 -070055import java.util.HashSet;
Wei Wang7dbe2ac2014-07-01 15:10:06 -070056import java.util.List;
Jeff Sharkeyc27359e2013-06-11 14:13:09 -070057import java.util.Locale;
Matthew Xie01e8e2a2013-04-11 16:36:26 -070058import java.util.Map;
Nick Pellyee1402d2009-10-02 20:34:18 -070059import java.util.Set;
Nick Pelly07b84cb2009-10-07 07:44:03 +020060import java.util.UUID;
Adam Lesinski6b31ff82016-04-11 12:18:18 -070061import java.util.concurrent.TimeoutException;
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -070062import java.util.concurrent.locks.ReentrantReadWriteLock;
Nick Pelly2d664882009-08-14 18:33:38 -070063
64/**
Scott Mainbeef8092009-11-03 18:17:59 -080065 * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
66 * lets you perform fundamental Bluetooth tasks, such as initiate
67 * device discovery, query a list of bonded (paired) devices,
68 * instantiate a {@link BluetoothDevice} using a known MAC address, and create
69 * a {@link BluetoothServerSocket} to listen for connection requests from other
Matthew Xieabb65582013-05-29 10:19:06 -070070 * devices, and start a scan for Bluetooth LE devices.
Scott Mainbeef8092009-11-03 18:17:59 -080071 *
72 * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
Marie Janssen36354fb2017-01-12 16:00:30 -080073 * adapter, call the {@link BluetoothManager#getAdapter} function on {@link BluetoothManager}.
74 * On JELLY_BEAN_MR1 and below you will need to use the static {@link #getDefaultAdapter}
75 * method instead.
76 * </p><p>
Scott Mainbeef8092009-11-03 18:17:59 -080077 * Fundamentally, this is your starting point for all
78 * Bluetooth actions. Once you have the local adapter, you can get a set of
79 * {@link BluetoothDevice} objects representing all paired devices with
80 * {@link #getBondedDevices()}; start device discovery with
81 * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
82 * listen for incoming connection requests with
Jack He910201b2017-08-22 16:06:54 -070083 * {@link #listenUsingRfcommWithServiceRecord(String, UUID)}; or start a scan for
Matthew Xieabb65582013-05-29 10:19:06 -070084 * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
Marie Janssen36354fb2017-01-12 16:00:30 -080085 * </p>
86 * <p>This class is thread safe.</p>
Scott Mainbeef8092009-11-03 18:17:59 -080087 * <p class="note"><strong>Note:</strong>
88 * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
89 * permission and some also require the
90 * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
Marie Janssen36354fb2017-01-12 16:00:30 -080091 * </p>
Joe Fernandezda4e2ab2011-12-20 10:38:34 -080092 * <div class="special reference">
93 * <h3>Developer Guides</h3>
Hemal Patele2cf8672016-08-17 13:18:14 -070094 * <p>
Jack He910201b2017-08-22 16:06:54 -070095 * For more information about using Bluetooth, read the <a href=
Hemal Patele2cf8672016-08-17 13:18:14 -070096 * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
97 * guide.
98 * </p>
Joe Fernandezda4e2ab2011-12-20 10:38:34 -080099 * </div>
100 *
Scott Mainbeef8092009-11-03 18:17:59 -0800101 * {@see BluetoothDevice}
102 * {@see BluetoothServerSocket}
Nick Pelly2d664882009-08-14 18:33:38 -0700103 */
104public final class BluetoothAdapter {
105 private static final String TAG = "BluetoothAdapter";
fredc3c719642012-04-12 00:02:00 -0700106 private static final boolean DBG = true;
Matthew Xie80b7fb42012-08-29 00:12:29 -0700107 private static final boolean VDBG = false;
Nick Pelly2d664882009-08-14 18:33:38 -0700108
Nick Pelly7482a802009-09-08 13:15:33 -0700109 /**
Svet Ganov252a6192015-05-12 19:13:36 -0700110 * Default MAC address reported to a client that does not have the
111 * android.permission.LOCAL_MAC_ADDRESS permission.
112 *
113 * @hide
114 */
115 public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
116
117 /**
Nick Pelly8a1cd0c2009-09-08 17:40:43 -0700118 * Sentinel error value for this class. Guaranteed to not equal any other
119 * integer constant in this class. Provided as a convenience for functions
120 * that require a sentinel error value, for example:
121 * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
122 * BluetoothAdapter.ERROR)</code>
123 */
Nick Pellydac4c0d2009-09-10 10:21:56 -0700124 public static final int ERROR = Integer.MIN_VALUE;
Nick Pelly8a1cd0c2009-09-08 17:40:43 -0700125
126 /**
Nick Pelly7482a802009-09-08 13:15:33 -0700127 * Broadcast Action: The state of the local Bluetooth adapter has been
128 * changed.
129 * <p>For example, Bluetooth has been turned on or off.
Nick Pellydac4c0d2009-09-10 10:21:56 -0700130 * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
Nick Pelly7482a802009-09-08 13:15:33 -0700131 * #EXTRA_PREVIOUS_STATE} containing the new and old states
132 * respectively.
133 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
134 */
135 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
136 public static final String ACTION_STATE_CHANGED =
Nick Pellydac4c0d2009-09-10 10:21:56 -0700137 "android.bluetooth.adapter.action.STATE_CHANGED";
Nick Pelly2d664882009-08-14 18:33:38 -0700138
Nick Pelly7482a802009-09-08 13:15:33 -0700139 /**
140 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
141 * intents to request the current power state. Possible values are:
142 * {@link #STATE_OFF},
143 * {@link #STATE_TURNING_ON},
144 * {@link #STATE_ON},
145 * {@link #STATE_TURNING_OFF},
146 */
147 public static final String EXTRA_STATE =
Nick Pellydac4c0d2009-09-10 10:21:56 -0700148 "android.bluetooth.adapter.extra.STATE";
Nick Pelly7482a802009-09-08 13:15:33 -0700149 /**
150 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
151 * intents to request the previous power state. Possible values are:
152 * {@link #STATE_OFF},
153 * {@link #STATE_TURNING_ON},
154 * {@link #STATE_ON},
Etan Cohen017ad5c2015-04-23 18:25:08 -0700155 * {@link #STATE_TURNING_OFF}
Nick Pelly7482a802009-09-08 13:15:33 -0700156 */
157 public static final String EXTRA_PREVIOUS_STATE =
Nick Pellydac4c0d2009-09-10 10:21:56 -0700158 "android.bluetooth.adapter.extra.PREVIOUS_STATE";
Nick Pelly2d664882009-08-14 18:33:38 -0700159
Tor Norbye27ce6cf2015-04-23 17:10:21 -0700160 /** @hide */
161 @IntDef({STATE_OFF, STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, STATE_BLE_TURNING_ON,
162 STATE_BLE_ON, STATE_BLE_TURNING_OFF})
163 @Retention(RetentionPolicy.SOURCE)
Jack He910201b2017-08-22 16:06:54 -0700164 public @interface AdapterState {
165 }
Tor Norbye27ce6cf2015-04-23 17:10:21 -0700166
Nick Pelly7482a802009-09-08 13:15:33 -0700167 /**
168 * Indicates the local Bluetooth adapter is off.
169 */
Nick Pellydac4c0d2009-09-10 10:21:56 -0700170 public static final int STATE_OFF = 10;
Nick Pelly7482a802009-09-08 13:15:33 -0700171 /**
172 * Indicates the local Bluetooth adapter is turning on. However local
173 * clients should wait for {@link #STATE_ON} before attempting to
174 * use the adapter.
175 */
Nick Pellydac4c0d2009-09-10 10:21:56 -0700176 public static final int STATE_TURNING_ON = 11;
Nick Pelly7482a802009-09-08 13:15:33 -0700177 /**
178 * Indicates the local Bluetooth adapter is on, and ready for use.
179 */
Nick Pellydac4c0d2009-09-10 10:21:56 -0700180 public static final int STATE_ON = 12;
Nick Pelly7482a802009-09-08 13:15:33 -0700181 /**
182 * Indicates the local Bluetooth adapter is turning off. Local clients
183 * should immediately attempt graceful disconnection of any remote links.
184 */
Nick Pellydac4c0d2009-09-10 10:21:56 -0700185 public static final int STATE_TURNING_OFF = 13;
Nick Pelly7482a802009-09-08 13:15:33 -0700186
187 /**
Nitin Arora7688f222015-03-02 15:03:51 -0800188 * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on.
Jack He910201b2017-08-22 16:06:54 -0700189 *
Nitin Arora7688f222015-03-02 15:03:51 -0800190 * @hide
191 */
192 public static final int STATE_BLE_TURNING_ON = 14;
193
194 /**
195 * Indicates the local Bluetooth adapter is in LE only mode.
Jack He910201b2017-08-22 16:06:54 -0700196 *
Nitin Arora7688f222015-03-02 15:03:51 -0800197 * @hide
198 */
199 public static final int STATE_BLE_ON = 15;
200
201 /**
202 * Indicates the local Bluetooth adapter is turning off LE only mode.
Jack He910201b2017-08-22 16:06:54 -0700203 *
Nitin Arora7688f222015-03-02 15:03:51 -0800204 * @hide
205 */
206 public static final int STATE_BLE_TURNING_OFF = 16;
207
208 /**
Marie Janssenf46373a2016-12-13 10:51:02 -0800209 * Human-readable string helper for AdapterState
Jack He910201b2017-08-22 16:06:54 -0700210 *
Marie Janssenf46373a2016-12-13 10:51:02 -0800211 * @hide
212 */
213 public static String nameForState(@AdapterState int state) {
Jack He910201b2017-08-22 16:06:54 -0700214 switch (state) {
215 case STATE_OFF:
216 return "OFF";
217 case STATE_TURNING_ON:
218 return "TURNING_ON";
219 case STATE_ON:
220 return "ON";
221 case STATE_TURNING_OFF:
222 return "TURNING_OFF";
223 case STATE_BLE_TURNING_ON:
224 return "BLE_TURNING_ON";
225 case STATE_BLE_ON:
226 return "BLE_ON";
227 case STATE_BLE_TURNING_OFF:
228 return "BLE_TURNING_OFF";
229 default:
230 return "?!?!? (" + state + ")";
Marie Janssenf46373a2016-12-13 10:51:02 -0800231 }
232 }
233
234 /**
Nick Pellydc704352009-09-24 11:14:15 -0700235 * Activity Action: Show a system activity that requests discoverable mode.
Scott Maina7848ce2009-11-19 17:00:19 -0800236 * This activity will also request the user to turn on Bluetooth if it
Nick Pellyb450b312009-09-28 10:33:55 -0700237 * is not currently enabled.
Nick Pellydc704352009-09-24 11:14:15 -0700238 * <p>Discoverable mode is equivalent to {@link
239 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
240 * this Bluetooth adapter when they perform a discovery.
Scott Maina7848ce2009-11-19 17:00:19 -0800241 * <p>For privacy, Android is not discoverable by default.
242 * <p>The sender of this Intent can optionally use extra field {@link
Nick Pellydc704352009-09-24 11:14:15 -0700243 * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
244 * discoverability. Currently the default duration is 120 seconds, and
245 * maximum duration is capped at 300 seconds for each request.
246 * <p>Notification of the result of this activity is posted using the
247 * {@link android.app.Activity#onActivityResult} callback. The
248 * <code>resultCode</code>
Michael Chan2e233832009-11-05 18:29:01 -0800249 * will be the duration (in seconds) of discoverability or
250 * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
251 * discoverability or an error has occurred.
Nick Pellydc704352009-09-24 11:14:15 -0700252 * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
Scott Maina7848ce2009-11-19 17:00:19 -0800253 * for global notification whenever the scan mode changes. For example, an
254 * application can be notified when the device has ended discoverability.
Nick Pellyb450b312009-09-28 10:33:55 -0700255 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pellydc704352009-09-24 11:14:15 -0700256 */
257 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
258 public static final String ACTION_REQUEST_DISCOVERABLE =
259 "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
260
261 /**
262 * Used as an optional int extra field in {@link
263 * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
264 * for discoverability in seconds. The current default is 120 seconds, and
265 * requests over 300 seconds will be capped. These values could change.
266 */
267 public static final String EXTRA_DISCOVERABLE_DURATION =
268 "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
269
270 /**
Nick Pellyb450b312009-09-28 10:33:55 -0700271 * Activity Action: Show a system activity that allows the user to turn on
272 * Bluetooth.
273 * <p>This system activity will return once Bluetooth has completed turning
274 * on, or the user has decided not to turn Bluetooth on.
275 * <p>Notification of the result of this activity is posted using the
276 * {@link android.app.Activity#onActivityResult} callback. The
277 * <code>resultCode</code>
Michael Chan2e233832009-11-05 18:29:01 -0800278 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
279 * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
280 * has rejected the request or an error has occurred.
Nick Pellyb450b312009-09-28 10:33:55 -0700281 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
282 * for global notification whenever Bluetooth is turned on or off.
283 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
284 */
285 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
286 public static final String ACTION_REQUEST_ENABLE =
287 "android.bluetooth.adapter.action.REQUEST_ENABLE";
288
289 /**
Svetoslav Ganov5682fb82016-06-29 17:31:44 -0700290 * Activity Action: Show a system activity that allows the user to turn off
291 * Bluetooth. This is used only if permission review is enabled which is for
292 * apps targeting API less than 23 require a permission review before any of
293 * the app's components can run.
294 * <p>This system activity will return once Bluetooth has completed turning
295 * off, or the user has decided not to turn Bluetooth off.
296 * <p>Notification of the result of this activity is posted using the
297 * {@link android.app.Activity#onActivityResult} callback. The
298 * <code>resultCode</code>
299 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
300 * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
301 * has rejected the request or an error has occurred.
302 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
303 * for global notification whenever Bluetooth is turned on or off.
304 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
305 *
306 * @hide
307 */
308 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
309 public static final String ACTION_REQUEST_DISABLE =
310 "android.bluetooth.adapter.action.REQUEST_DISABLE";
311
312 /**
Wei Wang43c66e22015-03-19 15:09:56 -0700313 * Activity Action: Show a system activity that allows user to enable BLE scans even when
314 * Bluetooth is turned off.<p>
315 *
316 * Notification of result of this activity is posted using
317 * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
318 * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
319 * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
320 * error occurred.
321 *
322 * @hide
323 */
324 @SystemApi
325 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
326 public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
327 "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
328
329 /**
Nick Pelly7482a802009-09-08 13:15:33 -0700330 * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
331 * has changed.
Nick Pellydac4c0d2009-09-10 10:21:56 -0700332 * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
Nick Pelly7482a802009-09-08 13:15:33 -0700333 * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
334 * respectively.
335 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
336 */
337 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
338 public static final String ACTION_SCAN_MODE_CHANGED =
Nick Pellydac4c0d2009-09-10 10:21:56 -0700339 "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
Nick Pelly7482a802009-09-08 13:15:33 -0700340
341 /**
342 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
343 * intents to request the current scan mode. Possible values are:
344 * {@link #SCAN_MODE_NONE},
345 * {@link #SCAN_MODE_CONNECTABLE},
346 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
347 */
Nick Pellydac4c0d2009-09-10 10:21:56 -0700348 public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
Nick Pelly7482a802009-09-08 13:15:33 -0700349 /**
350 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
351 * intents to request the previous scan mode. Possible values are:
352 * {@link #SCAN_MODE_NONE},
353 * {@link #SCAN_MODE_CONNECTABLE},
354 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
355 */
356 public static final String EXTRA_PREVIOUS_SCAN_MODE =
Nick Pellydac4c0d2009-09-10 10:21:56 -0700357 "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
Nick Pelly7482a802009-09-08 13:15:33 -0700358
Tor Norbye27ce6cf2015-04-23 17:10:21 -0700359 /** @hide */
360 @IntDef({SCAN_MODE_NONE, SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE})
361 @Retention(RetentionPolicy.SOURCE)
Jack He910201b2017-08-22 16:06:54 -0700362 public @interface ScanMode {
363 }
Tor Norbye27ce6cf2015-04-23 17:10:21 -0700364
Nick Pelly7482a802009-09-08 13:15:33 -0700365 /**
366 * Indicates that both inquiry scan and page scan are disabled on the local
367 * Bluetooth adapter. Therefore this device is neither discoverable
368 * nor connectable from remote Bluetooth devices.
369 */
Nick Pellydac4c0d2009-09-10 10:21:56 -0700370 public static final int SCAN_MODE_NONE = 20;
Nick Pelly7482a802009-09-08 13:15:33 -0700371 /**
372 * Indicates that inquiry scan is disabled, but page scan is enabled on the
373 * local Bluetooth adapter. Therefore this device is not discoverable from
374 * remote Bluetooth devices, but is connectable from remote devices that
375 * have previously discovered this device.
376 */
Nick Pellydac4c0d2009-09-10 10:21:56 -0700377 public static final int SCAN_MODE_CONNECTABLE = 21;
Nick Pelly7482a802009-09-08 13:15:33 -0700378 /**
379 * Indicates that both inquiry scan and page scan are enabled on the local
380 * Bluetooth adapter. Therefore this device is both discoverable and
381 * connectable from remote Bluetooth devices.
382 */
Nick Pellydac4c0d2009-09-10 10:21:56 -0700383 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
Nick Pelly2d664882009-08-14 18:33:38 -0700384
Nick Pellydac4c0d2009-09-10 10:21:56 -0700385 /**
386 * Broadcast Action: The local Bluetooth adapter has started the remote
387 * device discovery process.
388 * <p>This usually involves an inquiry scan of about 12 seconds, followed
389 * by a page scan of each new device to retrieve its Bluetooth name.
390 * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
391 * remote Bluetooth devices are found.
392 * <p>Device discovery is a heavyweight procedure. New connections to
393 * remote Bluetooth devices should not be attempted while discovery is in
394 * progress, and existing connections will experience limited bandwidth
395 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
396 * discovery.
397 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
398 */
399 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
400 public static final String ACTION_DISCOVERY_STARTED =
401 "android.bluetooth.adapter.action.DISCOVERY_STARTED";
402 /**
403 * Broadcast Action: The local Bluetooth adapter has finished the device
404 * discovery process.
405 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
406 */
407 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
408 public static final String ACTION_DISCOVERY_FINISHED =
409 "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
410
411 /**
412 * Broadcast Action: The local Bluetooth adapter has changed its friendly
413 * Bluetooth name.
414 * <p>This name is visible to remote Bluetooth devices.
415 * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
416 * the name.
417 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
418 */
419 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
420 public static final String ACTION_LOCAL_NAME_CHANGED =
421 "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
422 /**
423 * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
424 * intents to request the local Bluetooth name.
425 */
426 public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
427
Jaikumar Ganesh2af07762010-08-24 17:36:13 -0700428 /**
429 * Intent used to broadcast the change in connection state of the local
430 * Bluetooth adapter to a profile of the remote device. When the adapter is
431 * not connected to any profiles of any remote devices and it attempts a
432 * connection to a profile this intent will sent. Once connected, this intent
433 * will not be sent for any more connection attempts to any profiles of any
434 * remote device. When the adapter disconnects from the last profile its
435 * connected to of any remote device, this intent will be sent.
436 *
437 * <p> This intent is useful for applications that are only concerned about
438 * whether the local adapter is connected to any profile of any device and
439 * are not really concerned about which profile. For example, an application
440 * which displays an icon to display whether Bluetooth is connected or not
441 * can use this intent.
442 *
443 * <p>This intent will have 3 extras:
Jaikumar Ganeshf9660ec2011-02-01 16:47:11 -0800444 * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
445 * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
Jaikumar Ganesh2af07762010-08-24 17:36:13 -0700446 * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
447 *
Jaikumar Ganeshf9660ec2011-02-01 16:47:11 -0800448 * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
449 * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
Jaikumar Ganesh2af07762010-08-24 17:36:13 -0700450 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
451 *
452 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
453 */
454 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
455 public static final String ACTION_CONNECTION_STATE_CHANGED =
Jack He910201b2017-08-22 16:06:54 -0700456 "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
Jaikumar Ganesh2af07762010-08-24 17:36:13 -0700457
458 /**
459 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
460 *
461 * This extra represents the current connection state.
462 */
463 public static final String EXTRA_CONNECTION_STATE =
Jack He910201b2017-08-22 16:06:54 -0700464 "android.bluetooth.adapter.extra.CONNECTION_STATE";
Jaikumar Ganesh2af07762010-08-24 17:36:13 -0700465
466 /**
467 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
468 *
469 * This extra represents the previous connection state.
470 */
471 public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
Jack He910201b2017-08-22 16:06:54 -0700472 "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
Jaikumar Ganesh2af07762010-08-24 17:36:13 -0700473
Nitin Arora7688f222015-03-02 15:03:51 -0800474 /**
475 * Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
Jack He910201b2017-08-22 16:06:54 -0700476 *
Nitin Arora7688f222015-03-02 15:03:51 -0800477 * @hide
478 */
Wei Wang5a685692015-06-01 12:14:28 -0700479 @SystemApi
Nitin Arora7688f222015-03-02 15:03:51 -0800480 public static final String ACTION_BLE_STATE_CHANGED =
Jack He910201b2017-08-22 16:06:54 -0700481 "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
Nitin Arora7688f222015-03-02 15:03:51 -0800482
483 /**
Stanley Tngcf381862017-04-17 22:35:45 -0700484 * Intent used to broadcast the change in the Bluetooth address
485 * of the local Bluetooth adapter.
486 * <p>Always contains the extra field {@link
487 * #EXTRA_BLUETOOTH_ADDRESS} containing the Bluetooth address.
488 *
489 * Note: only system level processes are allowed to send this
490 * defined broadcast.
491 *
492 * @hide
493 */
494 public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED =
Jack He910201b2017-08-22 16:06:54 -0700495 "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED";
Stanley Tngcf381862017-04-17 22:35:45 -0700496
497 /**
498 * Used as a String extra field in {@link
499 * #ACTION_BLUETOOTH_ADDRESS_CHANGED} intent to store the local
500 * Bluetooth address.
501 *
502 * @hide
503 */
504 public static final String EXTRA_BLUETOOTH_ADDRESS =
Jack He910201b2017-08-22 16:06:54 -0700505 "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS";
Stanley Tngcf381862017-04-17 22:35:45 -0700506
507 /**
Nitin Arora7688f222015-03-02 15:03:51 -0800508 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
509 * by BLE Always on enabled application to know the ACL_CONNECTED event
510 * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection
511 * as Bluetooth LE is the only feature available in STATE_BLE_ON
512 *
513 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which
514 * works in Bluetooth state STATE_ON
Jack He910201b2017-08-22 16:06:54 -0700515 *
Nitin Arora7688f222015-03-02 15:03:51 -0800516 * @hide
517 */
518 public static final String ACTION_BLE_ACL_CONNECTED =
Jack He910201b2017-08-22 16:06:54 -0700519 "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";
Nitin Arora7688f222015-03-02 15:03:51 -0800520
521 /**
522 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
523 * by BLE Always on enabled application to know the ACL_DISCONNECTED event
524 * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth
525 * LE is the only feature available in STATE_BLE_ON
526 *
527 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which
528 * works in Bluetooth state STATE_ON
Jack He910201b2017-08-22 16:06:54 -0700529 *
Nitin Arora7688f222015-03-02 15:03:51 -0800530 * @hide
531 */
532 public static final String ACTION_BLE_ACL_DISCONNECTED =
Jack He910201b2017-08-22 16:06:54 -0700533 "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
Nitin Arora7688f222015-03-02 15:03:51 -0800534
Jaikumar Ganesh2af07762010-08-24 17:36:13 -0700535 /** The profile is in disconnected state */
Jack He910201b2017-08-22 16:06:54 -0700536 public static final int STATE_DISCONNECTED = 0;
Jaikumar Ganesh2af07762010-08-24 17:36:13 -0700537 /** The profile is in connecting state */
Jack He910201b2017-08-22 16:06:54 -0700538 public static final int STATE_CONNECTING = 1;
Jaikumar Ganesh2af07762010-08-24 17:36:13 -0700539 /** The profile is in connected state */
Jack He910201b2017-08-22 16:06:54 -0700540 public static final int STATE_CONNECTED = 2;
Jaikumar Ganesh2af07762010-08-24 17:36:13 -0700541 /** The profile is in disconnecting state */
542 public static final int STATE_DISCONNECTING = 3;
543
Nick Pelly79b3ff82009-10-08 00:12:45 +0200544 /** @hide */
fredc3c719642012-04-12 00:02:00 -0700545 public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
Nitin Arora7688f222015-03-02 15:03:51 -0800546 private final IBinder mToken;
Nick Pelly79b3ff82009-10-08 00:12:45 +0200547
Casper Bondec0a7c932015-04-09 09:24:48 +0200548
Jack He910201b2017-08-22 16:06:54 -0700549 /**
550 * When creating a ServerSocket using listenUsingRfcommOn() or
551 * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create
552 * a ServerSocket that auto assigns a channel number to the first
553 * bluetooth socket.
554 * The channel number assigned to this first Bluetooth Socket will
555 * be stored in the ServerSocket, and reused for subsequent Bluetooth
556 * sockets.
557 *
558 * @hide
559 */
Casper Bondec0a7c932015-04-09 09:24:48 +0200560 public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2;
561
562
Nick Pellydac4c0d2009-09-10 10:21:56 -0700563 private static final int ADDRESS_LENGTH = 17;
Nick Pelly2d664882009-08-14 18:33:38 -0700564
Nick Pelly79b3ff82009-10-08 00:12:45 +0200565 /**
Jake Hamby04c71382010-09-21 13:39:53 -0700566 * Lazily initialized singleton. Guaranteed final after first object
Nick Pelly79b3ff82009-10-08 00:12:45 +0200567 * constructed.
568 */
569 private static BluetoothAdapter sAdapter;
570
Wei Wang4c2da322014-07-23 23:34:00 -0700571 private static BluetoothLeScanner sBluetoothLeScanner;
572 private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
Jakub Pawlowskib74a8cd2017-01-16 07:21:01 -0800573 private static PeriodicAdvertisingManager sPeriodicAdvertisingManager;
Wei Wang4c2da322014-07-23 23:34:00 -0700574
fredc3c719642012-04-12 00:02:00 -0700575 private final IBluetoothManager mManagerService;
576 private IBluetooth mService;
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700577 private final ReentrantReadWriteLock mServiceLock =
Jack He910201b2017-08-22 16:06:54 -0700578 new ReentrantReadWriteLock();
Nick Pelly2d664882009-08-14 18:33:38 -0700579
Wei Wangff517632014-03-11 22:22:41 -0700580 private final Object mLock = new Object();
Wei Wang4c2da322014-07-23 23:34:00 -0700581 private final Map<LeScanCallback, ScanCallback> mLeScanClients;
Matthew Xie6e1b7652011-08-25 16:45:58 -0700582
Nick Pelly2d664882009-08-14 18:33:38 -0700583 /**
Nick Pelly79b3ff82009-10-08 00:12:45 +0200584 * Get a handle to the default local Bluetooth adapter.
585 * <p>Currently Android only supports one Bluetooth adapter, but the API
586 * could be extended to support more. This will always return the default
587 * adapter.
Marie Janssen36354fb2017-01-12 16:00:30 -0800588 * </p>
Jack He910201b2017-08-22 16:06:54 -0700589 *
590 * @return the default local adapter, or null if Bluetooth is not supported on this hardware
591 * platform
Nick Pelly79b3ff82009-10-08 00:12:45 +0200592 */
593 public static synchronized BluetoothAdapter getDefaultAdapter() {
594 if (sAdapter == null) {
fredc3c719642012-04-12 00:02:00 -0700595 IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
Nick Pelly79b3ff82009-10-08 00:12:45 +0200596 if (b != null) {
fredc3c719642012-04-12 00:02:00 -0700597 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
598 sAdapter = new BluetoothAdapter(managerService);
Jaikumar Ganesh88445232012-01-25 16:16:48 -0800599 } else {
600 Log.e(TAG, "Bluetooth binder is null");
Nick Pelly79b3ff82009-10-08 00:12:45 +0200601 }
602 }
603 return sAdapter;
604 }
605
606 /**
607 * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
Nick Pelly2d664882009-08-14 18:33:38 -0700608 */
fredc3c719642012-04-12 00:02:00 -0700609 BluetoothAdapter(IBluetoothManager managerService) {
610
611 if (managerService == null) {
612 throw new IllegalArgumentException("bluetooth manager service is null");
Nick Pelly2d664882009-08-14 18:33:38 -0700613 }
fredc3c719642012-04-12 00:02:00 -0700614 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700615 mServiceLock.writeLock().lock();
fredc3c719642012-04-12 00:02:00 -0700616 mService = managerService.registerAdapter(mManagerCallback);
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700617 } catch (RemoteException e) {
618 Log.e(TAG, "", e);
619 } finally {
620 mServiceLock.writeLock().unlock();
621 }
fredc3c719642012-04-12 00:02:00 -0700622 mManagerService = managerService;
Wei Wang4c2da322014-07-23 23:34:00 -0700623 mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
Nitin Arora7688f222015-03-02 15:03:51 -0800624 mToken = new Binder();
Nick Pelly2d664882009-08-14 18:33:38 -0700625 }
626
627 /**
Nick Pelly753da532009-08-19 11:00:00 -0700628 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
629 * address.
630 * <p>Valid Bluetooth hardware addresses must be upper case, in a format
Nick Pellydac4c0d2009-09-10 10:21:56 -0700631 * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
632 * available to validate a Bluetooth address.
Nick Pelly753da532009-08-19 11:00:00 -0700633 * <p>A {@link BluetoothDevice} will always be returned for a valid
634 * hardware address, even if this adapter has never seen that device.
Nick Pelly7482a802009-09-08 13:15:33 -0700635 *
Nick Pelly2d664882009-08-14 18:33:38 -0700636 * @param address valid Bluetooth MAC address
Nick Pelly753da532009-08-19 11:00:00 -0700637 * @throws IllegalArgumentException if address is invalid
Nick Pelly2d664882009-08-14 18:33:38 -0700638 */
639 public BluetoothDevice getRemoteDevice(String address) {
640 return new BluetoothDevice(address);
641 }
642
643 /**
Nick Pellyd3fca952011-12-07 15:03:55 -0800644 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
645 * address.
646 * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
647 * expects the address in network byte order (MSB first).
648 * <p>A {@link BluetoothDevice} will always be returned for a valid
649 * hardware address, even if this adapter has never seen that device.
650 *
651 * @param address Bluetooth MAC address (6 bytes)
652 * @throws IllegalArgumentException if address is invalid
653 */
654 public BluetoothDevice getRemoteDevice(byte[] address) {
655 if (address == null || address.length != 6) {
656 throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
657 }
Jeff Sharkeyc27359e2013-06-11 14:13:09 -0700658 return new BluetoothDevice(String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X",
Nick Pellyd3fca952011-12-07 15:03:55 -0800659 address[0], address[1], address[2], address[3], address[4], address[5]));
660 }
661
662 /**
Prerepa Viswanadham1afd3f42014-10-15 16:36:01 -0700663 * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
664 * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
665 * supported on this device.
Wei Wang4c2da322014-07-23 23:34:00 -0700666 * <p>
667 * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
668 * on this device before calling this method.
Wei Wangb464cfd2014-05-20 06:30:20 +0000669 */
670 public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
Nitin Arora7688f222015-03-02 15:03:51 -0800671 if (!getLeAccess()) return null;
Jack He910201b2017-08-22 16:06:54 -0700672 synchronized (mLock) {
Wei Wang4c2da322014-07-23 23:34:00 -0700673 if (sBluetoothLeAdvertiser == null) {
674 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
675 }
676 }
677 return sBluetoothLeAdvertiser;
Wei Wangb464cfd2014-05-20 06:30:20 +0000678 }
679
680 /**
Jakub Pawlowskib74a8cd2017-01-16 07:21:01 -0800681 * Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising
682 * operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic
683 * Advertising is not supported on this device.
684 * <p>
685 * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
686 * supported on this device before calling this method.
Jack He910201b2017-08-22 16:06:54 -0700687 *
Jakub Pawlowski8d0c4ba2017-03-29 17:00:44 -0700688 * @hide
Jakub Pawlowskib74a8cd2017-01-16 07:21:01 -0800689 */
690 public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
Jack He910201b2017-08-22 16:06:54 -0700691 if (!getLeAccess()) {
692 return null;
Jakub Pawlowskib74a8cd2017-01-16 07:21:01 -0800693 }
Jack He910201b2017-08-22 16:06:54 -0700694
695 if (!isLePeriodicAdvertisingSupported()) {
696 return null;
697 }
698
699 synchronized (mLock) {
700 if (sPeriodicAdvertisingManager == null) {
701 sPeriodicAdvertisingManager =
702 new PeriodicAdvertisingManager(mManagerService);
703 }
704 }
705 return sPeriodicAdvertisingManager;
Jakub Pawlowskib74a8cd2017-01-16 07:21:01 -0800706 }
707
708 /**
Wei Wangb464cfd2014-05-20 06:30:20 +0000709 * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
710 */
711 public BluetoothLeScanner getBluetoothLeScanner() {
Nitin Arora7688f222015-03-02 15:03:51 -0800712 if (!getLeAccess()) return null;
Jack He910201b2017-08-22 16:06:54 -0700713 synchronized (mLock) {
Wei Wang4c2da322014-07-23 23:34:00 -0700714 if (sBluetoothLeScanner == null) {
715 sBluetoothLeScanner = new BluetoothLeScanner(mManagerService);
716 }
717 }
718 return sBluetoothLeScanner;
Wei Wangb464cfd2014-05-20 06:30:20 +0000719 }
720
721 /**
Nick Pelly7482a802009-09-08 13:15:33 -0700722 * Return true if Bluetooth is currently enabled and ready for use.
723 * <p>Equivalent to:
724 * <code>getBluetoothState() == STATE_ON</code>
Nick Pelly2d664882009-08-14 18:33:38 -0700725 *
Nick Pelly7482a802009-09-08 13:15:33 -0700726 * @return true if the local adapter is turned on
Nick Pelly2d664882009-08-14 18:33:38 -0700727 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -0700728 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pelly2d664882009-08-14 18:33:38 -0700729 public boolean isEnabled() {
730 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700731 mServiceLock.readLock().lock();
732 if (mService != null) return mService.isEnabled();
733 } catch (RemoteException e) {
734 Log.e(TAG, "", e);
735 } finally {
736 mServiceLock.readLock().unlock();
737 }
738
Nick Pelly2d664882009-08-14 18:33:38 -0700739 return false;
740 }
741
742 /**
Nitin Arora7688f222015-03-02 15:03:51 -0800743 * Return true if Bluetooth LE(Always BLE On feature) is currently
744 * enabled and ready for use
745 * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON
746 *
747 * @return true if the local Bluetooth LE adapter is turned on
748 * @hide
749 */
Wei Wang5a685692015-06-01 12:14:28 -0700750 @SystemApi
751 public boolean isLeEnabled() {
Jack He910201b2017-08-22 16:06:54 -0700752 final int state = getLeState();
753 if (DBG) Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
754 return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON);
Nitin Arora7688f222015-03-02 15:03:51 -0800755 }
756
757 /**
Marie Janssen6eb20462016-12-28 14:13:21 -0800758 * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
Nitin Arora7688f222015-03-02 15:03:51 -0800759 *
760 * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
761 * to STATE_OFF and completely shut-down Bluetooth
762 *
763 * <p> If the Adapter state is STATE_ON, This would unregister the existance of
764 * special Bluetooth LE application and hence the further turning off of Bluetooth
765 * from UI would ensure the complete turn-off of Bluetooth rather than staying back
766 * BLE only state
767 *
768 * <p>This is an asynchronous call: it will return immediately, and
769 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
770 * to be notified of subsequent adapter state changes If this call returns
771 * true, then the adapter state will immediately transition from {@link
772 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
773 * later transition to either {@link #STATE_BLE_ON} or {@link
774 * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications
775 * If this call returns false then there was an
776 * immediate problem that will prevent the QAdapter from being turned off -
777 * such as the QAadapter already being turned off.
778 *
Jack He910201b2017-08-22 16:06:54 -0700779 * @return true to indicate success, or false on immediate error
Nitin Arora7688f222015-03-02 15:03:51 -0800780 * @hide
781 */
Wei Wang5a685692015-06-01 12:14:28 -0700782 @SystemApi
Nitin Arora7688f222015-03-02 15:03:51 -0800783 public boolean disableBLE() {
Wei Wang3acb7e82015-04-26 17:04:29 -0700784 if (!isBleScanAlwaysAvailable()) return false;
Nitin Arora7688f222015-03-02 15:03:51 -0800785
786 int state = getLeState();
Marie Janssen6eb20462016-12-28 14:13:21 -0800787 if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) {
788 String packageName = ActivityThread.currentPackageName();
Jack He910201b2017-08-22 16:06:54 -0700789 if (DBG) Log.d(TAG, "disableBLE(): de-registering " + packageName);
Nitin Arora7688f222015-03-02 15:03:51 -0800790 try {
Marie Janssen6eb20462016-12-28 14:13:21 -0800791 mManagerService.updateBleAppCount(mToken, false, packageName);
Nitin Arora7688f222015-03-02 15:03:51 -0800792 } catch (RemoteException e) {
793 Log.e(TAG, "", e);
794 }
795 return true;
Nitin Arora7688f222015-03-02 15:03:51 -0800796 }
797
Jack He910201b2017-08-22 16:06:54 -0700798 if (DBG) Log.d(TAG, "disableBLE(): Already disabled");
Nitin Arora7688f222015-03-02 15:03:51 -0800799 return false;
800 }
801
802 /**
Marie Janssen6eb20462016-12-28 14:13:21 -0800803 * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
Nitin Arora7688f222015-03-02 15:03:51 -0800804 *
Marie Janssen6eb20462016-12-28 14:13:21 -0800805 * enableBLE registers the existence of an app using only LE functions.
806 *
807 * enableBLE may enable Bluetooth to an LE only mode so that an app can use
808 * LE related features (BluetoothGatt or BluetoothGattServer classes)
809 *
810 * If the user disables Bluetooth while an app is registered to use LE only features,
811 * Bluetooth will remain on in LE only mode for the app.
812 *
813 * When Bluetooth is in LE only mode, it is not shown as ON to the UI.
814 *
815 * <p>This is an asynchronous call: it returns immediately, and
Nitin Arora7688f222015-03-02 15:03:51 -0800816 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
Marie Janssen6eb20462016-12-28 14:13:21 -0800817 * to be notified of adapter state changes.
818 *
819 * If this call returns * true, then the adapter state is either in a mode where
820 * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
821 * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
822 *
823 * If this call returns false then there was an immediate problem that prevents the
824 * adapter from being turned on - such as Airplane mode.
825 *
826 * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
Nitin Arora7688f222015-03-02 15:03:51 -0800827 * states, It includes all the classic Bluetooth Adapter states along with
828 * internal BLE only states
829 *
Jack He910201b2017-08-22 16:06:54 -0700830 * @return true to indicate Bluetooth LE will be available, or false on immediate error
Nitin Arora7688f222015-03-02 15:03:51 -0800831 * @hide
832 */
Wei Wang5a685692015-06-01 12:14:28 -0700833 @SystemApi
Nitin Arora7688f222015-03-02 15:03:51 -0800834 public boolean enableBLE() {
Wei Wang3acb7e82015-04-26 17:04:29 -0700835 if (!isBleScanAlwaysAvailable()) return false;
Nitin Arora7688f222015-03-02 15:03:51 -0800836
Nitin Arora7688f222015-03-02 15:03:51 -0800837 try {
Marie Janssen6eb20462016-12-28 14:13:21 -0800838 String packageName = ActivityThread.currentPackageName();
839 mManagerService.updateBleAppCount(mToken, true, packageName);
Marie Janssen257f8fe2016-10-25 10:47:51 -0700840 if (isLeEnabled()) {
841 if (DBG) Log.d(TAG, "enableBLE(): Bluetooth already enabled");
842 return true;
843 }
844 if (DBG) Log.d(TAG, "enableBLE(): Calling enable");
Marie Janssen6eb20462016-12-28 14:13:21 -0800845 return mManagerService.enable(packageName);
Nitin Arora7688f222015-03-02 15:03:51 -0800846 } catch (RemoteException e) {
847 Log.e(TAG, "", e);
848 }
849
850 return false;
851 }
852
853 /**
Nick Pelly7482a802009-09-08 13:15:33 -0700854 * Get the current state of the local Bluetooth adapter.
855 * <p>Possible return values are
856 * {@link #STATE_OFF},
857 * {@link #STATE_TURNING_ON},
858 * {@link #STATE_ON},
859 * {@link #STATE_TURNING_OFF}.
Nick Pelly2d664882009-08-14 18:33:38 -0700860 *
Nick Pelly7482a802009-09-08 13:15:33 -0700861 * @return current state of Bluetooth adapter
Nick Pelly2d664882009-08-14 18:33:38 -0700862 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -0700863 @RequiresPermission(Manifest.permission.BLUETOOTH)
864 @AdapterState
Nick Pelly7482a802009-09-08 13:15:33 -0700865 public int getState() {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700866 int state = BluetoothAdapter.STATE_OFF;
867
Nick Pelly2d664882009-08-14 18:33:38 -0700868 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700869 mServiceLock.readLock().lock();
870 if (mService != null) {
871 state = mService.getState();
fredc3c719642012-04-12 00:02:00 -0700872 }
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700873 } catch (RemoteException e) {
874 Log.e(TAG, "", e);
875 } finally {
876 mServiceLock.readLock().unlock();
877 }
878
879 // Consider all internal states as OFF
880 if (state == BluetoothAdapter.STATE_BLE_ON
Jack He910201b2017-08-22 16:06:54 -0700881 || state == BluetoothAdapter.STATE_BLE_TURNING_ON
882 || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
883 if (VDBG) {
884 Log.d(TAG,
885 "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF");
886 }
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700887 state = BluetoothAdapter.STATE_OFF;
888 }
Jack He910201b2017-08-22 16:06:54 -0700889 if (VDBG) {
890 Log.d(TAG,
891 "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(
892 state));
893 }
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700894 return state;
Nick Pelly2d664882009-08-14 18:33:38 -0700895 }
896
897 /**
Nitin Arora7688f222015-03-02 15:03:51 -0800898 * Get the current state of the local Bluetooth adapter
899 * <p>This returns current internal state of Adapter including LE ON/OFF
900 *
901 * <p>Possible return values are
902 * {@link #STATE_OFF},
903 * {@link #STATE_BLE_TURNING_ON},
904 * {@link #STATE_BLE_ON},
905 * {@link #STATE_TURNING_ON},
906 * {@link #STATE_ON},
907 * {@link #STATE_TURNING_OFF},
908 * {@link #STATE_BLE_TURNING_OFF}.
Nitin Arora7688f222015-03-02 15:03:51 -0800909 *
910 * @return current state of Bluetooth adapter
911 * @hide
912 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -0700913 @RequiresPermission(Manifest.permission.BLUETOOTH)
914 @AdapterState
Nitin Arora7688f222015-03-02 15:03:51 -0800915 public int getLeState() {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700916 int state = BluetoothAdapter.STATE_OFF;
917
Nitin Arora7688f222015-03-02 15:03:51 -0800918 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700919 mServiceLock.readLock().lock();
920 if (mService != null) {
921 state = mService.getState();
Nitin Arora7688f222015-03-02 15:03:51 -0800922 }
923 } catch (RemoteException e) {
924 Log.e(TAG, "", e);
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700925 } finally {
926 mServiceLock.readLock().unlock();
Nitin Arora7688f222015-03-02 15:03:51 -0800927 }
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700928
Jack He910201b2017-08-22 16:06:54 -0700929 if (VDBG) Log.d(TAG, "getLeState() returning " + BluetoothAdapter.nameForState(state));
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -0700930 return state;
Nitin Arora7688f222015-03-02 15:03:51 -0800931 }
932
933 boolean getLeAccess() {
Jack He910201b2017-08-22 16:06:54 -0700934 if (getLeState() == STATE_ON) {
Nitin Arora7688f222015-03-02 15:03:51 -0800935 return true;
Jack He910201b2017-08-22 16:06:54 -0700936 } else if (getLeState() == STATE_BLE_ON) {
Nitin Arora7688f222015-03-02 15:03:51 -0800937 return true; // TODO: FILTER SYSTEM APPS HERE <--
Jack He910201b2017-08-22 16:06:54 -0700938 }
Nitin Arora7688f222015-03-02 15:03:51 -0800939
940 return false;
941 }
942
943 /**
Scott Maincdd8b7e2009-12-09 16:07:39 -0800944 * Turn on the local Bluetooth adapter&mdash;do not use without explicit
945 * user action to turn on Bluetooth.
Nick Pelly7482a802009-09-08 13:15:33 -0700946 * <p>This powers on the underlying Bluetooth hardware, and starts all
947 * Bluetooth system services.
Scott Maincdd8b7e2009-12-09 16:07:39 -0800948 * <p class="caution"><strong>Bluetooth should never be enabled without
949 * direct user consent</strong>. If you want to turn on Bluetooth in order
950 * to create a wireless connection, you should use the {@link
951 * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
952 * user permission to turn on Bluetooth. The {@link #enable()} method is
953 * provided only for applications that include a user interface for changing
954 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick8946f232009-09-25 16:31:39 +0400955 * <p>This is an asynchronous call: it will return immediately, and
Nick Pelly7482a802009-09-08 13:15:33 -0700956 * clients should listen for {@link #ACTION_STATE_CHANGED}
957 * to be notified of subsequent adapter state changes. If this call returns
958 * true, then the adapter state will immediately transition from {@link
959 * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
960 * later transition to either {@link #STATE_OFF} or {@link
961 * #STATE_ON}. If this call returns false then there was an
962 * immediate problem that will prevent the adapter from being turned on -
963 * such as Airplane mode, or the adapter is already turned on.
Nick Pelly7482a802009-09-08 13:15:33 -0700964 *
Jack He910201b2017-08-22 16:06:54 -0700965 * @return true to indicate adapter startup has begun, or false on immediate error
Nick Pelly2d664882009-08-14 18:33:38 -0700966 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -0700967 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pelly2d664882009-08-14 18:33:38 -0700968 public boolean enable() {
Marie Janssenf46373a2016-12-13 10:51:02 -0800969 if (isEnabled()) {
970 if (DBG) Log.d(TAG, "enable(): BT already enabled!");
Ganesh Ganapathi Battafa1a5272012-08-08 15:35:49 -0700971 return true;
972 }
Nick Pelly2d664882009-08-14 18:33:38 -0700973 try {
Svetoslav Ganov5682fb82016-06-29 17:31:44 -0700974 return mManagerService.enable(ActivityThread.currentPackageName());
Jack He910201b2017-08-22 16:06:54 -0700975 } catch (RemoteException e) {
976 Log.e(TAG, "", e);
977 }
Nick Pelly2d664882009-08-14 18:33:38 -0700978 return false;
979 }
980
981 /**
Scott Maincdd8b7e2009-12-09 16:07:39 -0800982 * Turn off the local Bluetooth adapter&mdash;do not use without explicit
983 * user action to turn off Bluetooth.
Nick Pelly7482a802009-09-08 13:15:33 -0700984 * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
985 * system services, and powers down the underlying Bluetooth hardware.
Jake Hamby04c71382010-09-21 13:39:53 -0700986 * <p class="caution"><strong>Bluetooth should never be disabled without
Scott Maincdd8b7e2009-12-09 16:07:39 -0800987 * direct user consent</strong>. The {@link #disable()} method is
988 * provided only for applications that include a user interface for changing
989 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick8946f232009-09-25 16:31:39 +0400990 * <p>This is an asynchronous call: it will return immediately, and
Nick Pelly7482a802009-09-08 13:15:33 -0700991 * clients should listen for {@link #ACTION_STATE_CHANGED}
992 * to be notified of subsequent adapter state changes. If this call returns
993 * true, then the adapter state will immediately transition from {@link
994 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
995 * later transition to either {@link #STATE_OFF} or {@link
996 * #STATE_ON}. If this call returns false then there was an
997 * immediate problem that will prevent the adapter from being turned off -
998 * such as the adapter already being turned off.
Nick Pelly2d664882009-08-14 18:33:38 -0700999 *
Jack He910201b2017-08-22 16:06:54 -07001000 * @return true to indicate adapter shutdown has begun, or false on immediate error
Nick Pelly2d664882009-08-14 18:33:38 -07001001 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001002 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pelly2d664882009-08-14 18:33:38 -07001003 public boolean disable() {
1004 try {
Svetoslav Ganov5682fb82016-06-29 17:31:44 -07001005 return mManagerService.disable(ActivityThread.currentPackageName(), true);
Jack He910201b2017-08-22 16:06:54 -07001006 } catch (RemoteException e) {
1007 Log.e(TAG, "", e);
1008 }
Jaikumar Ganeshd95bd9c2012-03-06 17:15:16 -08001009 return false;
1010 }
1011
1012 /**
1013 * Turn off the local Bluetooth adapter and don't persist the setting.
1014 *
1015 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1016 * permission
1017 *
Jack He910201b2017-08-22 16:06:54 -07001018 * @return true to indicate adapter shutdown has begun, or false on immediate error
Jaikumar Ganeshd95bd9c2012-03-06 17:15:16 -08001019 * @hide
1020 */
1021 public boolean disable(boolean persist) {
fredc3c719642012-04-12 00:02:00 -07001022
Jaikumar Ganeshd95bd9c2012-03-06 17:15:16 -08001023 try {
Svetoslav Ganov5682fb82016-06-29 17:31:44 -07001024 return mManagerService.disable(ActivityThread.currentPackageName(), persist);
Jack He910201b2017-08-22 16:06:54 -07001025 } catch (RemoteException e) {
1026 Log.e(TAG, "", e);
1027 }
Nick Pelly2d664882009-08-14 18:33:38 -07001028 return false;
1029 }
1030
Nick Pelly7482a802009-09-08 13:15:33 -07001031 /**
1032 * Returns the hardware address of the local Bluetooth adapter.
1033 * <p>For example, "00:11:22:AA:BB:CC".
Nick Pelly7482a802009-09-08 13:15:33 -07001034 *
1035 * @return Bluetooth hardware address as string
1036 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001037 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pelly2d664882009-08-14 18:33:38 -07001038 public String getAddress() {
1039 try {
fredc3c719642012-04-12 00:02:00 -07001040 return mManagerService.getAddress();
Jack He910201b2017-08-22 16:06:54 -07001041 } catch (RemoteException e) {
1042 Log.e(TAG, "", e);
1043 }
Nick Pelly2d664882009-08-14 18:33:38 -07001044 return null;
1045 }
1046
1047 /**
Nick Pelly7482a802009-09-08 13:15:33 -07001048 * Get the friendly Bluetooth name of the local Bluetooth adapter.
1049 * <p>This name is visible to remote Bluetooth devices.
1050 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pelly2d664882009-08-14 18:33:38 -07001051 *
Nick Pelly7482a802009-09-08 13:15:33 -07001052 * @return the Bluetooth name, or null on error
Nick Pelly2d664882009-08-14 18:33:38 -07001053 */
1054 public String getName() {
1055 try {
fredc50ef8e02012-04-20 14:47:08 -07001056 return mManagerService.getName();
Jack He910201b2017-08-22 16:06:54 -07001057 } catch (RemoteException e) {
1058 Log.e(TAG, "", e);
1059 }
Nick Pelly2d664882009-08-14 18:33:38 -07001060 return null;
1061 }
1062
1063 /**
Ajay Panickere1601fa2015-07-28 16:52:09 -07001064 * Factory reset bluetooth settings.
1065 *
1066 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
1067 * permission
1068 *
1069 * @return true to indicate that the config file was successfully cleared
Ajay Panickere1601fa2015-07-28 16:52:09 -07001070 * @hide
1071 */
1072 public boolean factoryReset() {
1073 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001074 mServiceLock.readLock().lock();
Ajay Panickere1601fa2015-07-28 16:52:09 -07001075 if (mService != null) {
1076 return mService.factoryReset();
1077 }
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001078 SystemProperties.set("persist.bluetooth.factoryreset", "true");
1079 } catch (RemoteException e) {
1080 Log.e(TAG, "", e);
1081 } finally {
1082 mServiceLock.readLock().unlock();
1083 }
Ajay Panickere1601fa2015-07-28 16:52:09 -07001084 return false;
1085 }
1086
1087 /**
Jaikumar Ganesha2dbad42010-11-23 20:03:10 -08001088 * Get the UUIDs supported by the local Bluetooth adapter.
1089 *
1090 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1091 *
1092 * @return the UUIDs supported by the local Bluetooth Adapter.
1093 * @hide
1094 */
1095 public ParcelUuid[] getUuids() {
Matthew Xie70c4b332011-11-16 12:27:57 -08001096 if (getState() != STATE_ON) return null;
Jaikumar Ganesha2dbad42010-11-23 20:03:10 -08001097 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001098 mServiceLock.readLock().lock();
1099 if (mService != null) return mService.getUuids();
1100 } catch (RemoteException e) {
1101 Log.e(TAG, "", e);
1102 } finally {
1103 mServiceLock.readLock().unlock();
1104 }
Jaikumar Ganesha2dbad42010-11-23 20:03:10 -08001105 return null;
1106 }
1107
1108 /**
Jake Hambyc7e84882010-09-16 18:12:51 -07001109 * Set the friendly Bluetooth name of the local Bluetooth adapter.
Nick Pelly7482a802009-09-08 13:15:33 -07001110 * <p>This name is visible to remote Bluetooth devices.
Jake Hambyc7e84882010-09-16 18:12:51 -07001111 * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
1112 * encoding, although many remote devices can only display the first
1113 * 40 characters, and some may be limited to just 20.
Jaikumar Ganesh1c8dba02010-08-09 16:54:03 -07001114 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1115 * will return false. After turning on Bluetooth,
1116 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1117 * to get the updated value.
Nick Pelly2d664882009-08-14 18:33:38 -07001118 *
Nick Pelly7482a802009-09-08 13:15:33 -07001119 * @param name a valid Bluetooth name
Jack He910201b2017-08-22 16:06:54 -07001120 * @return true if the name was set, false otherwise
Nick Pelly2d664882009-08-14 18:33:38 -07001121 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001122 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pelly2d664882009-08-14 18:33:38 -07001123 public boolean setName(String name) {
Jaikumar Ganeshfc0c1822010-08-06 19:03:13 -07001124 if (getState() != STATE_ON) return false;
Nick Pelly2d664882009-08-14 18:33:38 -07001125 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001126 mServiceLock.readLock().lock();
1127 if (mService != null) return mService.setName(name);
1128 } catch (RemoteException e) {
1129 Log.e(TAG, "", e);
1130 } finally {
1131 mServiceLock.readLock().unlock();
1132 }
Nick Pelly2d664882009-08-14 18:33:38 -07001133 return false;
1134 }
1135
1136 /**
Pulkit Bhuwalka4729ea82017-08-16 21:52:04 -07001137 * Sets the {@link BluetoothClass} Bluetooth Class of Device (CoD) of
1138 * the local Bluetooth adapter.
1139 *
1140 * @param bluetoothClass {@link BluetoothClass} to set the local Bluetooth adapter to.
1141 * @return true if successful, false if unsuccessful.
1142 *
1143 * @hide
1144 */
1145 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
1146 public boolean setBluetoothClass(BluetoothClass bluetoothClass) {
1147 if (getState() != STATE_ON) return false;
1148 try {
1149 mServiceLock.readLock().lock();
1150 if (mService != null) return mService.setBluetoothClass(bluetoothClass);
1151 } catch (RemoteException e) {
1152 Log.e(TAG, "", e);
1153 } finally {
1154 mServiceLock.readLock().unlock();
1155 }
1156 return false;
1157 }
1158
1159 /**
Jake Hambyc7e84882010-09-16 18:12:51 -07001160 * Get the current Bluetooth scan mode of the local Bluetooth adapter.
Nick Pelly7482a802009-09-08 13:15:33 -07001161 * <p>The Bluetooth scan mode determines if the local adapter is
1162 * connectable and/or discoverable from remote Bluetooth devices.
1163 * <p>Possible values are:
1164 * {@link #SCAN_MODE_NONE},
1165 * {@link #SCAN_MODE_CONNECTABLE},
1166 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganesh1c8dba02010-08-09 16:54:03 -07001167 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1168 * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
1169 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1170 * to get the updated value.
Nick Pelly7482a802009-09-08 13:15:33 -07001171 *
1172 * @return scan mode
Nick Pelly2d664882009-08-14 18:33:38 -07001173 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001174 @RequiresPermission(Manifest.permission.BLUETOOTH)
1175 @ScanMode
Nick Pelly2d664882009-08-14 18:33:38 -07001176 public int getScanMode() {
Jaikumar Ganeshfc0c1822010-08-06 19:03:13 -07001177 if (getState() != STATE_ON) return SCAN_MODE_NONE;
Nick Pelly2d664882009-08-14 18:33:38 -07001178 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001179 mServiceLock.readLock().lock();
1180 if (mService != null) return mService.getScanMode();
1181 } catch (RemoteException e) {
1182 Log.e(TAG, "", e);
1183 } finally {
1184 mServiceLock.readLock().unlock();
1185 }
Nick Pelly7482a802009-09-08 13:15:33 -07001186 return SCAN_MODE_NONE;
Nick Pelly2d664882009-08-14 18:33:38 -07001187 }
1188
1189 /**
Nick Pelly7482a802009-09-08 13:15:33 -07001190 * Set the Bluetooth scan mode of the local Bluetooth adapter.
1191 * <p>The Bluetooth scan mode determines if the local adapter is
1192 * connectable and/or discoverable from remote Bluetooth devices.
Nick Pelly694305c2009-09-25 15:00:29 -07001193 * <p>For privacy reasons, discoverable mode is automatically turned off
1194 * after <code>duration</code> seconds. For example, 120 seconds should be
1195 * enough for a remote device to initiate and complete its discovery
1196 * process.
Nick Pelly7482a802009-09-08 13:15:33 -07001197 * <p>Valid scan mode values are:
1198 * {@link #SCAN_MODE_NONE},
1199 * {@link #SCAN_MODE_CONNECTABLE},
1200 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganesh1c8dba02010-08-09 16:54:03 -07001201 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1202 * will return false. After turning on Bluetooth,
1203 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1204 * to get the updated value.
Nick Pellydc704352009-09-24 11:14:15 -07001205 * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}
1206 * <p>Applications cannot set the scan mode. They should use
1207 * <code>startActivityForResult(
1208 * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
1209 * </code>instead.
Nick Pelly7482a802009-09-08 13:15:33 -07001210 *
1211 * @param mode valid scan mode
Jack He910201b2017-08-22 16:06:54 -07001212 * @param duration time in seconds to apply scan mode, only used for {@link
1213 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
1214 * @return true if the scan mode was set, false otherwise
Nick Pellydc704352009-09-24 11:14:15 -07001215 * @hide
Nick Pelly2d664882009-08-14 18:33:38 -07001216 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001217 public boolean setScanMode(@ScanMode int mode, int duration) {
Jaikumar Ganeshfc0c1822010-08-06 19:03:13 -07001218 if (getState() != STATE_ON) return false;
Nick Pelly2d664882009-08-14 18:33:38 -07001219 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001220 mServiceLock.readLock().lock();
1221 if (mService != null) return mService.setScanMode(mode, duration);
1222 } catch (RemoteException e) {
1223 Log.e(TAG, "", e);
1224 } finally {
1225 mServiceLock.readLock().unlock();
1226 }
Nick Pelly7482a802009-09-08 13:15:33 -07001227 return false;
Nick Pelly2d664882009-08-14 18:33:38 -07001228 }
1229
Nick Pelly753da532009-08-19 11:00:00 -07001230 /** @hide */
Nick Pelly694305c2009-09-25 15:00:29 -07001231 public boolean setScanMode(int mode) {
Jaikumar Ganeshfc0c1822010-08-06 19:03:13 -07001232 if (getState() != STATE_ON) return false;
Srikanth Uppalab527e5f2012-04-04 03:33:26 -07001233 /* getDiscoverableTimeout() to use the latest from NV than use 0 */
1234 return setScanMode(mode, getDiscoverableTimeout());
Nick Pelly694305c2009-09-25 15:00:29 -07001235 }
1236
1237 /** @hide */
Nick Pelly2d664882009-08-14 18:33:38 -07001238 public int getDiscoverableTimeout() {
Jaikumar Ganeshfc0c1822010-08-06 19:03:13 -07001239 if (getState() != STATE_ON) return -1;
Nick Pelly2d664882009-08-14 18:33:38 -07001240 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001241 mServiceLock.readLock().lock();
1242 if (mService != null) return mService.getDiscoverableTimeout();
1243 } catch (RemoteException e) {
1244 Log.e(TAG, "", e);
1245 } finally {
1246 mServiceLock.readLock().unlock();
1247 }
Nick Pelly2d664882009-08-14 18:33:38 -07001248 return -1;
1249 }
1250
Nick Pelly753da532009-08-19 11:00:00 -07001251 /** @hide */
Nick Pelly2d664882009-08-14 18:33:38 -07001252 public void setDiscoverableTimeout(int timeout) {
Jaikumar Ganeshfc0c1822010-08-06 19:03:13 -07001253 if (getState() != STATE_ON) return;
Nick Pelly2d664882009-08-14 18:33:38 -07001254 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001255 mServiceLock.readLock().lock();
1256 if (mService != null) mService.setDiscoverableTimeout(timeout);
1257 } catch (RemoteException e) {
1258 Log.e(TAG, "", e);
1259 } finally {
1260 mServiceLock.readLock().unlock();
1261 }
Nick Pelly2d664882009-08-14 18:33:38 -07001262 }
1263
Nick Pellydac4c0d2009-09-10 10:21:56 -07001264 /**
Marie Janssene692bd32017-01-24 14:09:59 -08001265 * Get the end time of the latest remote device discovery process.
Jack He910201b2017-08-22 16:06:54 -07001266 *
1267 * @return the latest time that the bluetooth adapter was/will be in discovery mode, in
1268 * milliseconds since the epoch. This time can be in the future if {@link #startDiscovery()} has
1269 * been called recently.
Marie Janssene692bd32017-01-24 14:09:59 -08001270 * @hide
1271 */
1272 public long getDiscoveryEndMillis() {
1273 try {
1274 mServiceLock.readLock().lock();
1275 if (mService != null) return mService.getDiscoveryEndMillis();
1276 } catch (RemoteException e) {
1277 Log.e(TAG, "", e);
1278 } finally {
1279 mServiceLock.readLock().unlock();
1280 }
1281 return -1;
1282 }
1283
1284 /**
Nick Pellydac4c0d2009-09-10 10:21:56 -07001285 * Start the remote device discovery process.
1286 * <p>The discovery process usually involves an inquiry scan of about 12
1287 * seconds, followed by a page scan of each new device to retrieve its
1288 * Bluetooth name.
1289 * <p>This is an asynchronous call, it will return immediately. Register
1290 * for {@link #ACTION_DISCOVERY_STARTED} and {@link
1291 * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
1292 * discovery starts and completes. Register for {@link
1293 * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
1294 * are found.
1295 * <p>Device discovery is a heavyweight procedure. New connections to
1296 * remote Bluetooth devices should not be attempted while discovery is in
1297 * progress, and existing connections will experience limited bandwidth
1298 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
Scott Maina7848ce2009-11-19 17:00:19 -08001299 * discovery. Discovery is not managed by the Activity,
1300 * but is run as a system service, so an application should always call
1301 * {@link BluetoothAdapter#cancelDiscovery()} even if it
1302 * did not directly request a discovery, just to be sure.
Nick Pellydac4c0d2009-09-10 10:21:56 -07001303 * <p>Device discovery will only find remote devices that are currently
1304 * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
1305 * not discoverable by default, and need to be entered into a special mode.
Jaikumar Ganesh1c8dba02010-08-09 16:54:03 -07001306 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1307 * will return false. After turning on Bluetooth,
1308 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1309 * to get the updated value.
Nick Pellydac4c0d2009-09-10 10:21:56 -07001310 *
1311 * @return true on success, false on error
1312 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001313 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pelly2d664882009-08-14 18:33:38 -07001314 public boolean startDiscovery() {
Jaikumar Ganeshfc0c1822010-08-06 19:03:13 -07001315 if (getState() != STATE_ON) return false;
Nick Pelly2d664882009-08-14 18:33:38 -07001316 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001317 mServiceLock.readLock().lock();
1318 if (mService != null) return mService.startDiscovery();
1319 } catch (RemoteException e) {
1320 Log.e(TAG, "", e);
1321 } finally {
1322 mServiceLock.readLock().unlock();
1323 }
Nick Pelly2d664882009-08-14 18:33:38 -07001324 return false;
1325 }
1326
Nick Pellydac4c0d2009-09-10 10:21:56 -07001327 /**
1328 * Cancel the current device discovery process.
Jake Hambyc7e84882010-09-16 18:12:51 -07001329 * <p>Because discovery is a heavyweight procedure for the Bluetooth
Scott Maina7848ce2009-11-19 17:00:19 -08001330 * adapter, this method should always be called before attempting to connect
1331 * to a remote device with {@link
1332 * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
1333 * the Activity, but is run as a system service, so an application should
1334 * always call cancel discovery even if it did not directly request a
1335 * discovery, just to be sure.
Jaikumar Ganesh1c8dba02010-08-09 16:54:03 -07001336 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1337 * will return false. After turning on Bluetooth,
1338 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1339 * to get the updated value.
Nick Pellydac4c0d2009-09-10 10:21:56 -07001340 *
1341 * @return true on success, false on error
1342 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001343 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellydac4c0d2009-09-10 10:21:56 -07001344 public boolean cancelDiscovery() {
Jaikumar Ganeshfc0c1822010-08-06 19:03:13 -07001345 if (getState() != STATE_ON) return false;
Nick Pelly2d664882009-08-14 18:33:38 -07001346 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001347 mServiceLock.readLock().lock();
1348 if (mService != null) return mService.cancelDiscovery();
1349 } catch (RemoteException e) {
1350 Log.e(TAG, "", e);
1351 } finally {
1352 mServiceLock.readLock().unlock();
1353 }
Nick Pellydac4c0d2009-09-10 10:21:56 -07001354 return false;
Nick Pelly2d664882009-08-14 18:33:38 -07001355 }
1356
Nick Pellydac4c0d2009-09-10 10:21:56 -07001357 /**
1358 * Return true if the local Bluetooth adapter is currently in the device
1359 * discovery process.
1360 * <p>Device discovery is a heavyweight procedure. New connections to
1361 * remote Bluetooth devices should not be attempted while discovery is in
1362 * progress, and existing connections will experience limited bandwidth
1363 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1364 * discovery.
1365 * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
1366 * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
1367 * starts or completes.
Jaikumar Ganesh1c8dba02010-08-09 16:54:03 -07001368 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1369 * will return false. After turning on Bluetooth,
1370 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1371 * to get the updated value.
Nick Pellydac4c0d2009-09-10 10:21:56 -07001372 *
1373 * @return true if discovering
1374 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001375 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pelly2d664882009-08-14 18:33:38 -07001376 public boolean isDiscovering() {
Jaikumar Ganeshfc0c1822010-08-06 19:03:13 -07001377 if (getState() != STATE_ON) return false;
Nick Pelly2d664882009-08-14 18:33:38 -07001378 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001379 mServiceLock.readLock().lock();
1380 if (mService != null) return mService.isDiscovering();
1381 } catch (RemoteException e) {
1382 Log.e(TAG, "", e);
1383 } finally {
1384 mServiceLock.readLock().unlock();
1385 }
Nick Pelly2d664882009-08-14 18:33:38 -07001386 return false;
1387 }
1388
1389 /**
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001390 * Return true if the multi advertisement is supported by the chipset
1391 *
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001392 * @return true if Multiple Advertisement feature is supported
1393 */
1394 public boolean isMultipleAdvertisementSupported() {
1395 if (getState() != STATE_ON) return false;
1396 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001397 mServiceLock.readLock().lock();
1398 if (mService != null) return mService.isMultiAdvertisementSupported();
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001399 } catch (RemoteException e) {
1400 Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001401 } finally {
1402 mServiceLock.readLock().unlock();
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001403 }
1404 return false;
1405 }
1406
1407 /**
Wei Wang43c66e22015-03-19 15:09:56 -07001408 * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
1409 *
1410 * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
1411 * fetch scan results even when Bluetooth is turned off.<p>
1412 *
1413 * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
1414 *
1415 * @hide
1416 */
1417 @SystemApi
1418 public boolean isBleScanAlwaysAvailable() {
Wei Wang3acb7e82015-04-26 17:04:29 -07001419 try {
1420 return mManagerService.isBleScanAlwaysAvailable();
1421 } catch (RemoteException e) {
1422 Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e);
1423 return false;
1424 }
Wei Wang43c66e22015-03-19 15:09:56 -07001425 }
1426
1427 /**
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001428 * Return true if offloaded filters are supported
1429 *
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001430 * @return true if chipset supports on-chip filtering
1431 */
1432 public boolean isOffloadedFilteringSupported() {
Wei Wangbaa2d7c2015-05-07 16:25:33 -07001433 if (!getLeAccess()) return false;
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001434 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001435 mServiceLock.readLock().lock();
1436 if (mService != null) return mService.isOffloadedFilteringSupported();
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001437 } catch (RemoteException e) {
1438 Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001439 } finally {
1440 mServiceLock.readLock().unlock();
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001441 }
1442 return false;
1443 }
1444
1445 /**
1446 * Return true if offloaded scan batching is supported
1447 *
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001448 * @return true if chipset supports on-chip scan batching
1449 */
1450 public boolean isOffloadedScanBatchingSupported() {
Wei Wangbaa2d7c2015-05-07 16:25:33 -07001451 if (!getLeAccess()) return false;
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001452 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001453 mServiceLock.readLock().lock();
1454 if (mService != null) return mService.isOffloadedScanBatchingSupported();
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001455 } catch (RemoteException e) {
1456 Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e);
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001457 } finally {
1458 mServiceLock.readLock().unlock();
Prerepa Viswanadhamd9b0b0e2014-07-02 12:30:38 -07001459 }
1460 return false;
1461 }
1462
1463 /**
Jakub Pawlowski60d90302017-02-07 18:05:39 -08001464 * Return true if LE 2M PHY feature is supported.
1465 *
1466 * @return true if chipset supports LE 2M PHY feature
1467 */
1468 public boolean isLe2MPhySupported() {
1469 if (!getLeAccess()) return false;
1470 try {
1471 mServiceLock.readLock().lock();
1472 if (mService != null) return mService.isLe2MPhySupported();
1473 } catch (RemoteException e) {
1474 Log.e(TAG, "failed to get isExtendedAdvertisingSupported, error: ", e);
1475 } finally {
1476 mServiceLock.readLock().unlock();
1477 }
1478 return false;
1479 }
1480
1481 /**
1482 * Return true if LE Coded PHY feature is supported.
1483 *
1484 * @return true if chipset supports LE Coded PHY feature
1485 */
1486 public boolean isLeCodedPhySupported() {
1487 if (!getLeAccess()) return false;
1488 try {
1489 mServiceLock.readLock().lock();
1490 if (mService != null) return mService.isLeCodedPhySupported();
1491 } catch (RemoteException e) {
1492 Log.e(TAG, "failed to get isLeCodedPhySupported, error: ", e);
1493 } finally {
1494 mServiceLock.readLock().unlock();
1495 }
1496 return false;
1497 }
1498
1499 /**
Jakub Pawlowski842b81b2017-03-10 16:07:59 -08001500 * Return true if LE Extended Advertising feature is supported.
Jakub Pawlowski60d90302017-02-07 18:05:39 -08001501 *
Jakub Pawlowski842b81b2017-03-10 16:07:59 -08001502 * @return true if chipset supports LE Extended Advertising feature
Jakub Pawlowski60d90302017-02-07 18:05:39 -08001503 */
1504 public boolean isLeExtendedAdvertisingSupported() {
1505 if (!getLeAccess()) return false;
1506 try {
1507 mServiceLock.readLock().lock();
1508 if (mService != null) return mService.isLeExtendedAdvertisingSupported();
1509 } catch (RemoteException e) {
1510 Log.e(TAG, "failed to get isLeExtendedAdvertisingSupported, error: ", e);
1511 } finally {
1512 mServiceLock.readLock().unlock();
1513 }
1514 return false;
1515 }
1516
1517 /**
1518 * Return true if LE Periodic Advertising feature is supported.
1519 *
1520 * @return true if chipset supports LE Periodic Advertising feature
1521 */
1522 public boolean isLePeriodicAdvertisingSupported() {
1523 if (!getLeAccess()) return false;
1524 try {
1525 mServiceLock.readLock().lock();
1526 if (mService != null) return mService.isLePeriodicAdvertisingSupported();
1527 } catch (RemoteException e) {
1528 Log.e(TAG, "failed to get isLePeriodicAdvertisingSupported, error: ", e);
1529 } finally {
1530 mServiceLock.readLock().unlock();
1531 }
1532 return false;
1533 }
1534
1535 /**
Jakub Pawlowskidc3abd62017-04-21 04:59:55 -07001536 * Return the maximum LE advertising data length in bytes,
1537 * if LE Extended Advertising feature is supported, 0 otherwise.
Jakub Pawlowski1e2d5cb2017-03-16 18:22:36 -07001538 *
1539 * @return the maximum LE advertising data length.
1540 */
1541 public int getLeMaximumAdvertisingDataLength() {
1542 if (!getLeAccess()) return 0;
1543 try {
1544 mServiceLock.readLock().lock();
1545 if (mService != null) return mService.getLeMaximumAdvertisingDataLength();
1546 } catch (RemoteException e) {
1547 Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
1548 } finally {
1549 mServiceLock.readLock().unlock();
1550 }
1551 return 0;
1552 }
1553
1554 /**
Prerepa Viswanadham98d25c52015-04-07 14:36:53 -07001555 * Return true if hardware has entries available for matching beacons
1556 *
1557 * @return true if there are hw entries available for matching beacons
1558 * @hide
1559 */
1560 public boolean isHardwareTrackingFiltersAvailable() {
Wei Wangbaa2d7c2015-05-07 16:25:33 -07001561 if (!getLeAccess()) return false;
Prerepa Viswanadham98d25c52015-04-07 14:36:53 -07001562 try {
Prerepa Viswanadham79684212015-04-09 17:14:50 -07001563 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
1564 if (iGatt == null) {
1565 // BLE is not supported
1566 return false;
Prerepa Viswanadham98d25c52015-04-07 14:36:53 -07001567 }
Prerepa Viswanadham79684212015-04-09 17:14:50 -07001568 return (iGatt.numHwTrackFiltersAvailable() != 0);
Prerepa Viswanadham98d25c52015-04-07 14:36:53 -07001569 } catch (RemoteException e) {
1570 Log.e(TAG, "", e);
1571 }
1572 return false;
1573 }
1574
1575 /**
Prerepa Viswanadham53c97ae2014-07-22 17:00:09 -07001576 * Return the record of {@link BluetoothActivityEnergyInfo} object that
1577 * has the activity and energy info. This can be used to ascertain what
1578 * the controller has been up to, since the last sample.
Prerepa Viswanadham53c97ae2014-07-22 17:00:09 -07001579 *
Jack He910201b2017-08-22 16:06:54 -07001580 * @param updateType Type of info, cached vs refreshed.
1581 * @return a record with {@link BluetoothActivityEnergyInfo} or null if report is unavailable or
1582 * unsupported
Prerepa Viswanadham53c97ae2014-07-22 17:00:09 -07001583 * @hide
Jack He910201b2017-08-22 16:06:54 -07001584 * @deprecated use the asynchronous {@link #requestControllerActivityEnergyInfo(ResultReceiver)}
1585 * instead.
Prerepa Viswanadham53c97ae2014-07-22 17:00:09 -07001586 */
Adam Lesinski6b31ff82016-04-11 12:18:18 -07001587 @Deprecated
Prerepa Viswanadham53c97ae2014-07-22 17:00:09 -07001588 public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
Adam Lesinski6b31ff82016-04-11 12:18:18 -07001589 SynchronousResultReceiver receiver = new SynchronousResultReceiver();
Adam Lesinski39d90152016-05-10 14:00:03 -07001590 requestControllerActivityEnergyInfo(receiver);
Prerepa Viswanadham53c97ae2014-07-22 17:00:09 -07001591 try {
Adam Lesinski6b31ff82016-04-11 12:18:18 -07001592 SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
1593 if (result.bundle != null) {
1594 return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
1595 }
1596 } catch (TimeoutException e) {
1597 Log.e(TAG, "getControllerActivityEnergyInfo timed out");
1598 }
1599 return null;
1600 }
1601
1602 /**
1603 * Request the record of {@link BluetoothActivityEnergyInfo} object that
1604 * has the activity and energy info. This can be used to ascertain what
1605 * the controller has been up to, since the last sample.
1606 *
1607 * A null value for the activity info object may be sent if the bluetooth service is
1608 * unreachable or the device does not support reporting such information.
1609 *
Adam Lesinski6b31ff82016-04-11 12:18:18 -07001610 * @param result The callback to which to send the activity info.
1611 * @hide
1612 */
Adam Lesinski39d90152016-05-10 14:00:03 -07001613 public void requestControllerActivityEnergyInfo(ResultReceiver result) {
Adam Lesinski6b31ff82016-04-11 12:18:18 -07001614 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001615 mServiceLock.readLock().lock();
1616 if (mService != null) {
1617 mService.requestActivityInfo(result);
1618 result = null;
Prerepa Viswanadham53c97ae2014-07-22 17:00:09 -07001619 }
Prerepa Viswanadham53c97ae2014-07-22 17:00:09 -07001620 } catch (RemoteException e) {
1621 Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
Adam Lesinski39d90152016-05-10 14:00:03 -07001622 } finally {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001623 mServiceLock.readLock().unlock();
Adam Lesinski39d90152016-05-10 14:00:03 -07001624 if (result != null) {
1625 // Only send an immediate result if we failed.
1626 result.send(0, null);
1627 }
Prerepa Viswanadham53c97ae2014-07-22 17:00:09 -07001628 }
Prerepa Viswanadham53c97ae2014-07-22 17:00:09 -07001629 }
1630
1631 /**
Nick Pellydac4c0d2009-09-10 10:21:56 -07001632 * Return the set of {@link BluetoothDevice} objects that are bonded
1633 * (paired) to the local adapter.
Jaikumar Ganesh1c8dba02010-08-09 16:54:03 -07001634 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1635 * will return an empty set. After turning on Bluetooth,
1636 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1637 * to get the updated value.
Nick Pelly2d664882009-08-14 18:33:38 -07001638 *
Nick Pellydac4c0d2009-09-10 10:21:56 -07001639 * @return unmodifiable set of {@link BluetoothDevice}, or null on error
Nick Pelly2d664882009-08-14 18:33:38 -07001640 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001641 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pelly2d664882009-08-14 18:33:38 -07001642 public Set<BluetoothDevice> getBondedDevices() {
Jaikumar Ganesh1c8dba02010-08-09 16:54:03 -07001643 if (getState() != STATE_ON) {
Jaikumar Ganesh88445232012-01-25 16:16:48 -08001644 return toDeviceSet(new BluetoothDevice[0]);
Jaikumar Ganesh1c8dba02010-08-09 16:54:03 -07001645 }
Nick Pelly2d664882009-08-14 18:33:38 -07001646 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001647 mServiceLock.readLock().lock();
1648 if (mService != null) return toDeviceSet(mService.getBondedDevices());
fredc3c719642012-04-12 00:02:00 -07001649 return toDeviceSet(new BluetoothDevice[0]);
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001650 } catch (RemoteException e) {
1651 Log.e(TAG, "", e);
1652 } finally {
1653 mServiceLock.readLock().unlock();
1654 }
Nick Pelly2d664882009-08-14 18:33:38 -07001655 return null;
1656 }
1657
1658 /**
Bryce Lee9bb3a682016-10-09 12:54:42 -07001659 * Gets the currently supported profiles by the adapter.
1660 *
Jack He910201b2017-08-22 16:06:54 -07001661 * <p> This can be used to check whether a profile is supported before attempting
Bryce Lee9bb3a682016-10-09 12:54:42 -07001662 * to connect to its respective proxy.
1663 *
Jack He910201b2017-08-22 16:06:54 -07001664 * @return a list of integers indicating the ids of supported profiles as defined in {@link
1665 * BluetoothProfile}.
Bryce Lee9bb3a682016-10-09 12:54:42 -07001666 * @hide
1667 */
1668 public List<Integer> getSupportedProfiles() {
1669 final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
1670
1671 try {
1672 synchronized (mManagerCallback) {
1673 if (mService != null) {
1674 final long supportedProfilesBitMask = mService.getSupportedProfiles();
1675
1676 for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
1677 if ((supportedProfilesBitMask & (1 << i)) != 0) {
1678 supportedProfiles.add(i);
1679 }
1680 }
1681 }
1682 }
Marie Janssenf46373a2016-12-13 10:51:02 -08001683 } catch (RemoteException e) {
Jack He910201b2017-08-22 16:06:54 -07001684 Log.e(TAG, "getSupportedProfiles:", e);
Marie Janssenf46373a2016-12-13 10:51:02 -08001685 }
Bryce Lee9bb3a682016-10-09 12:54:42 -07001686 return supportedProfiles;
1687 }
1688
1689 /**
Jaikumar Ganesh8e8b26d2010-10-26 16:02:26 -07001690 * Get the current connection state of the local Bluetooth adapter.
1691 * This can be used to check whether the local Bluetooth adapter is connected
1692 * to any profile of any other remote Bluetooth Device.
1693 *
1694 * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
1695 * intent to get the connection state of the adapter.
1696 *
Jack He910201b2017-08-22 16:06:54 -07001697 * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, {@link
1698 * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
Jaikumar Ganesh8e8b26d2010-10-26 16:02:26 -07001699 * @hide
1700 */
1701 public int getConnectionState() {
1702 if (getState() != STATE_ON) return BluetoothAdapter.STATE_DISCONNECTED;
1703 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001704 mServiceLock.readLock().lock();
1705 if (mService != null) return mService.getAdapterConnectionState();
1706 } catch (RemoteException e) {
1707 Log.e(TAG, "getConnectionState:", e);
1708 } finally {
1709 mServiceLock.readLock().unlock();
1710 }
Jaikumar Ganesh8e8b26d2010-10-26 16:02:26 -07001711 return BluetoothAdapter.STATE_DISCONNECTED;
1712 }
1713
1714 /**
Jaikumar Ganesh53178422011-08-19 10:26:32 -07001715 * Get the current connection state of a profile.
1716 * This function can be used to check whether the local Bluetooth adapter
1717 * is connected to any remote device for a specific profile.
Scott Main3c0c5be2011-09-26 22:59:38 -07001718 * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
Jaikumar Ganeshc875f3a2011-08-23 12:21:55 -07001719 * {@link BluetoothProfile#A2DP}.
Jaikumar Ganesh53178422011-08-19 10:26:32 -07001720 *
Jaikumar Ganesh53178422011-08-19 10:26:32 -07001721 * <p> Return value can be one of
Jaikumar Ganeshc875f3a2011-08-23 12:21:55 -07001722 * {@link BluetoothProfile#STATE_DISCONNECTED},
1723 * {@link BluetoothProfile#STATE_CONNECTING},
1724 * {@link BluetoothProfile#STATE_CONNECTED},
1725 * {@link BluetoothProfile#STATE_DISCONNECTING}
Jaikumar Ganesh53178422011-08-19 10:26:32 -07001726 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001727 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganesh53178422011-08-19 10:26:32 -07001728 public int getProfileConnectionState(int profile) {
1729 if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED;
1730 try {
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001731 mServiceLock.readLock().lock();
1732 if (mService != null) return mService.getProfileConnectionState(profile);
Jaikumar Ganeshc875f3a2011-08-23 12:21:55 -07001733 } catch (RemoteException e) {
1734 Log.e(TAG, "getProfileConnectionState:", e);
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07001735 } finally {
1736 mServiceLock.readLock().unlock();
Jaikumar Ganeshc875f3a2011-08-23 12:21:55 -07001737 }
Jaikumar Ganesh53178422011-08-19 10:26:32 -07001738 return BluetoothProfile.STATE_DISCONNECTED;
1739 }
1740
1741 /**
Nick Pelly753da532009-08-19 11:00:00 -07001742 * Create a listening, secure RFCOMM Bluetooth socket.
1743 * <p>A remote device connecting to this socket will be authenticated and
Nick Pelly2d664882009-08-14 18:33:38 -07001744 * communication on this socket will be encrypted.
Nick Pelly753da532009-08-19 11:00:00 -07001745 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
Nick Pellyee1402d2009-10-02 20:34:18 -07001746 * connections from a listening {@link BluetoothServerSocket}.
Nick Pelly753da532009-08-19 11:00:00 -07001747 * <p>Valid RFCOMM channels are in range 1 to 30.
Nick Pellyee1402d2009-10-02 20:34:18 -07001748 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
Jack He910201b2017-08-22 16:06:54 -07001749 *
Nick Pelly753da532009-08-19 11:00:00 -07001750 * @param channel RFCOMM channel to listen on
1751 * @return a listening RFCOMM BluetoothServerSocket
Jack He910201b2017-08-22 16:06:54 -07001752 * @throws IOException on error, for example Bluetooth not available, or insufficient
1753 * permissions, or channel in use.
Nick Pellyee1402d2009-10-02 20:34:18 -07001754 * @hide
Nick Pelly2d664882009-08-14 18:33:38 -07001755 */
Nick Pelly753da532009-08-19 11:00:00 -07001756 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
Casper Bonde91276012015-05-08 14:32:24 +02001757 return listenUsingRfcommOn(channel, false, false);
Casper Bonde60d77c22015-04-21 13:12:05 +02001758 }
1759
1760 /**
1761 * Create a listening, secure RFCOMM Bluetooth socket.
1762 * <p>A remote device connecting to this socket will be authenticated and
1763 * communication on this socket will be encrypted.
1764 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1765 * connections from a listening {@link BluetoothServerSocket}.
1766 * <p>Valid RFCOMM channels are in range 1 to 30.
1767 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1768 * <p>To auto assign a channel without creating a SDP record use
1769 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
Jack He910201b2017-08-22 16:06:54 -07001770 *
Casper Bonde60d77c22015-04-21 13:12:05 +02001771 * @param channel RFCOMM channel to listen on
Jack He910201b2017-08-22 16:06:54 -07001772 * @param mitm enforce man-in-the-middle protection for authentication.
1773 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
1774 * connections.
Casper Bonde60d77c22015-04-21 13:12:05 +02001775 * @return a listening RFCOMM BluetoothServerSocket
Jack He910201b2017-08-22 16:06:54 -07001776 * @throws IOException on error, for example Bluetooth not available, or insufficient
1777 * permissions, or channel in use.
Casper Bonde60d77c22015-04-21 13:12:05 +02001778 * @hide
1779 */
Casper Bonde91276012015-05-08 14:32:24 +02001780 public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
1781 boolean min16DigitPin)
1782 throws IOException {
Nick Pelly2d664882009-08-14 18:33:38 -07001783 BluetoothServerSocket socket = new BluetoothServerSocket(
Casper Bonde91276012015-05-08 14:32:24 +02001784 BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm, min16DigitPin);
Nick Pellyee1402d2009-10-02 20:34:18 -07001785 int errno = socket.mSocket.bindListen();
Casper Bonde60d77c22015-04-21 13:12:05 +02001786 if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bondec0a7c932015-04-09 09:24:48 +02001787 socket.setChannel(socket.mSocket.getPort());
1788 }
Nick Pellyee1402d2009-10-02 20:34:18 -07001789 if (errno != 0) {
zzyfab62db2012-04-03 19:48:32 -07001790 //TODO(BT): Throw the same exception error code
1791 // that the previous code was using.
1792 //socket.mSocket.throwErrnoNative(errno);
1793 throw new IOException("Error: " + errno);
Nick Pelly2d664882009-08-14 18:33:38 -07001794 }
1795 return socket;
1796 }
1797
1798 /**
Nick Pellyee1402d2009-10-02 20:34:18 -07001799 * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
1800 * <p>A remote device connecting to this socket will be authenticated and
1801 * communication on this socket will be encrypted.
1802 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1803 * connections from a listening {@link BluetoothServerSocket}.
1804 * <p>The system will assign an unused RFCOMM channel to listen on.
1805 * <p>The system will also register a Service Discovery
1806 * Protocol (SDP) record with the local SDP server containing the specified
1807 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1808 * can use the same UUID to query our SDP server and discover which channel
1809 * to connect to. This SDP record will be removed when this socket is
1810 * closed, or if this application closes unexpectedly.
Nick Pelly07b84cb2009-10-07 07:44:03 +02001811 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1812 * connect to this socket from another device using the same {@link UUID}.
Jack He910201b2017-08-22 16:06:54 -07001813 *
Nick Pellyee1402d2009-10-02 20:34:18 -07001814 * @param name service name for SDP record
1815 * @param uuid uuid for SDP record
1816 * @return a listening RFCOMM BluetoothServerSocket
Jack He910201b2017-08-22 16:06:54 -07001817 * @throws IOException on error, for example Bluetooth not available, or insufficient
1818 * permissions, or channel in use.
Nick Pellyee1402d2009-10-02 20:34:18 -07001819 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001820 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pelly07b84cb2009-10-07 07:44:03 +02001821 public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
Nick Pellyee1402d2009-10-02 20:34:18 -07001822 throws IOException {
Jaikumar Ganesh203b5812010-12-23 12:57:02 -08001823 return createNewRfcommSocketAndRecord(name, uuid, true, true);
1824 }
1825
1826 /**
1827 * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
Mathias Jeppssonefd744d2011-03-21 15:06:52 +01001828 * <p>The link key is not required to be authenticated, i.e the communication may be
Jaikumar Ganesh203b5812010-12-23 12:57:02 -08001829 * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices,
Mathias Jeppssonefd744d2011-03-21 15:06:52 +01001830 * the link will be encrypted, as encryption is mandartory.
1831 * For legacy devices (pre Bluetooth 2.1 devices) the link will not
Jaikumar Ganesh203b5812010-12-23 12:57:02 -08001832 * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
1833 * encrypted and authenticated communication channel is desired.
1834 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1835 * connections from a listening {@link BluetoothServerSocket}.
1836 * <p>The system will assign an unused RFCOMM channel to listen on.
1837 * <p>The system will also register a Service Discovery
1838 * Protocol (SDP) record with the local SDP server containing the specified
1839 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1840 * can use the same UUID to query our SDP server and discover which channel
1841 * to connect to. This SDP record will be removed when this socket is
1842 * closed, or if this application closes unexpectedly.
1843 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1844 * connect to this socket from another device using the same {@link UUID}.
Jack He910201b2017-08-22 16:06:54 -07001845 *
Jaikumar Ganesh203b5812010-12-23 12:57:02 -08001846 * @param name service name for SDP record
1847 * @param uuid uuid for SDP record
1848 * @return a listening RFCOMM BluetoothServerSocket
Jack He910201b2017-08-22 16:06:54 -07001849 * @throws IOException on error, for example Bluetooth not available, or insufficient
1850 * permissions, or channel in use.
Jaikumar Ganesh203b5812010-12-23 12:57:02 -08001851 */
Tor Norbye27ce6cf2015-04-23 17:10:21 -07001852 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganesh203b5812010-12-23 12:57:02 -08001853 public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
1854 throws IOException {
1855 return createNewRfcommSocketAndRecord(name, uuid, false, false);
1856 }
1857
Jack He910201b2017-08-22 16:06:54 -07001858 /**
Mathias Jeppssonefd744d2011-03-21 15:06:52 +01001859 * Create a listening, encrypted,
1860 * RFCOMM Bluetooth socket with Service Record.
1861 * <p>The link will be encrypted, but the link key is not required to be authenticated
1862 * i.e the communication is vulnerable to Man In the Middle attacks. Use
1863 * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
1864 * <p> Use this socket if authentication of link key is not possible.
1865 * For example, for Bluetooth 2.1 devices, if any of the devices does not have
1866 * an input and output capability or just has the ability to display a numeric key,
1867 * a secure socket connection is not possible and this socket can be used.
1868 * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
1869 * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
1870 * For more details, refer to the Security Model section 5.2 (vol 3) of
1871 * Bluetooth Core Specification version 2.1 + EDR.
1872 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1873 * connections from a listening {@link BluetoothServerSocket}.
1874 * <p>The system will assign an unused RFCOMM channel to listen on.
1875 * <p>The system will also register a Service Discovery
1876 * Protocol (SDP) record with the local SDP server containing the specified
1877 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1878 * can use the same UUID to query our SDP server and discover which channel
1879 * to connect to. This SDP record will be removed when this socket is
1880 * closed, or if this application closes unexpectedly.
1881 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1882 * connect to this socket from another device using the same {@link UUID}.
1883 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Jack He910201b2017-08-22 16:06:54 -07001884 *
Mathias Jeppssonefd744d2011-03-21 15:06:52 +01001885 * @param name service name for SDP record
1886 * @param uuid uuid for SDP record
1887 * @return a listening RFCOMM BluetoothServerSocket
Jack He910201b2017-08-22 16:06:54 -07001888 * @throws IOException on error, for example Bluetooth not available, or insufficient
1889 * permissions, or channel in use.
Mathias Jeppssonefd744d2011-03-21 15:06:52 +01001890 * @hide
1891 */
1892 public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(
1893 String name, UUID uuid) throws IOException {
1894 return createNewRfcommSocketAndRecord(name, uuid, false, true);
1895 }
1896
zzyfab62db2012-04-03 19:48:32 -07001897
Jaikumar Ganesh203b5812010-12-23 12:57:02 -08001898 private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
1899 boolean auth, boolean encrypt) throws IOException {
Nick Pellyee1402d2009-10-02 20:34:18 -07001900 BluetoothServerSocket socket;
zzyfab62db2012-04-03 19:48:32 -07001901 socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth,
Jack He910201b2017-08-22 16:06:54 -07001902 encrypt, new ParcelUuid(uuid));
zzyfab62db2012-04-03 19:48:32 -07001903 socket.setServiceName(name);
1904 int errno = socket.mSocket.bindListen();
1905 if (errno != 0) {
1906 //TODO(BT): Throw the same exception error code
1907 // that the previous code was using.
1908 //socket.mSocket.throwErrnoNative(errno);
1909 throw new IOException("Error: " + errno);
Nick Pellyee1402d2009-10-02 20:34:18 -07001910 }
Nick Pellyee1402d2009-10-02 20:34:18 -07001911 return socket;
1912 }
1913
1914 /**
Nick Pelly2d664882009-08-14 18:33:38 -07001915 * Construct an unencrypted, unauthenticated, RFCOMM server socket.
1916 * Call #accept to retrieve connections to this socket.
Jack He910201b2017-08-22 16:06:54 -07001917 *
Nick Pelly2d664882009-08-14 18:33:38 -07001918 * @return An RFCOMM BluetoothServerSocket
Jack He910201b2017-08-22 16:06:54 -07001919 * @throws IOException On error, for example Bluetooth not available, or insufficient
1920 * permissions.
Nick Pelly753da532009-08-19 11:00:00 -07001921 * @hide
Nick Pelly2d664882009-08-14 18:33:38 -07001922 */
1923 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
1924 BluetoothServerSocket socket = new BluetoothServerSocket(
1925 BluetoothSocket.TYPE_RFCOMM, false, false, port);
Nick Pellyee1402d2009-10-02 20:34:18 -07001926 int errno = socket.mSocket.bindListen();
Jack He910201b2017-08-22 16:06:54 -07001927 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bondec0a7c932015-04-09 09:24:48 +02001928 socket.setChannel(socket.mSocket.getPort());
1929 }
Nick Pellyee1402d2009-10-02 20:34:18 -07001930 if (errno != 0) {
zzyfab62db2012-04-03 19:48:32 -07001931 //TODO(BT): Throw the same exception error code
1932 // that the previous code was using.
1933 //socket.mSocket.throwErrnoNative(errno);
1934 throw new IOException("Error: " + errno);
Nick Pelly2d664882009-08-14 18:33:38 -07001935 }
1936 return socket;
1937 }
1938
Jack He910201b2017-08-22 16:06:54 -07001939 /**
Mathias Jeppssonefd744d2011-03-21 15:06:52 +01001940 * Construct an encrypted, RFCOMM server socket.
1941 * Call #accept to retrieve connections to this socket.
Jack He910201b2017-08-22 16:06:54 -07001942 *
Mathias Jeppssonefd744d2011-03-21 15:06:52 +01001943 * @return An RFCOMM BluetoothServerSocket
Jack He910201b2017-08-22 16:06:54 -07001944 * @throws IOException On error, for example Bluetooth not available, or insufficient
1945 * permissions.
Mathias Jeppssonefd744d2011-03-21 15:06:52 +01001946 * @hide
1947 */
1948 public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port)
1949 throws IOException {
1950 BluetoothServerSocket socket = new BluetoothServerSocket(
1951 BluetoothSocket.TYPE_RFCOMM, false, true, port);
1952 int errno = socket.mSocket.bindListen();
Jack He910201b2017-08-22 16:06:54 -07001953 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bondec0a7c932015-04-09 09:24:48 +02001954 socket.setChannel(socket.mSocket.getPort());
1955 }
zzyfab62db2012-04-03 19:48:32 -07001956 if (errno < 0) {
1957 //TODO(BT): Throw the same exception error code
1958 // that the previous code was using.
1959 //socket.mSocket.throwErrnoNative(errno);
1960 throw new IOException("Error: " + errno);
Mathias Jeppssonefd744d2011-03-21 15:06:52 +01001961 }
1962 return socket;
1963 }
1964
Nick Pelly2d664882009-08-14 18:33:38 -07001965 /**
1966 * Construct a SCO server socket.
1967 * Call #accept to retrieve connections to this socket.
Jack He910201b2017-08-22 16:06:54 -07001968 *
Nick Pelly2d664882009-08-14 18:33:38 -07001969 * @return A SCO BluetoothServerSocket
Jack He910201b2017-08-22 16:06:54 -07001970 * @throws IOException On error, for example Bluetooth not available, or insufficient
1971 * permissions.
Nick Pelly753da532009-08-19 11:00:00 -07001972 * @hide
Nick Pelly2d664882009-08-14 18:33:38 -07001973 */
1974 public static BluetoothServerSocket listenUsingScoOn() throws IOException {
1975 BluetoothServerSocket socket = new BluetoothServerSocket(
1976 BluetoothSocket.TYPE_SCO, false, false, -1);
Nick Pellyee1402d2009-10-02 20:34:18 -07001977 int errno = socket.mSocket.bindListen();
zzyfab62db2012-04-03 19:48:32 -07001978 if (errno < 0) {
1979 //TODO(BT): Throw the same exception error code
1980 // that the previous code was using.
1981 //socket.mSocket.throwErrnoNative(errno);
Nick Pelly2d664882009-08-14 18:33:38 -07001982 }
1983 return socket;
1984 }
1985
Jaikumar Ganesh76965ca2010-09-09 15:37:57 -07001986 /**
Casper Bondec0a7c932015-04-09 09:24:48 +02001987 * Construct an encrypted, authenticated, L2CAP server socket.
1988 * Call #accept to retrieve connections to this socket.
Casper Bonde60d77c22015-04-21 13:12:05 +02001989 * <p>To auto assign a port without creating a SDP record use
1990 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack He910201b2017-08-22 16:06:54 -07001991 *
1992 * @param port the PSM to listen on
1993 * @param mitm enforce man-in-the-middle protection for authentication.
1994 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
1995 * connections.
Casper Bondec0a7c932015-04-09 09:24:48 +02001996 * @return An L2CAP BluetoothServerSocket
Jack He910201b2017-08-22 16:06:54 -07001997 * @throws IOException On error, for example Bluetooth not available, or insufficient
1998 * permissions.
Casper Bondec0a7c932015-04-09 09:24:48 +02001999 * @hide
2000 */
Casper Bonde91276012015-05-08 14:32:24 +02002001 public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
2002 throws IOException {
Casper Bondec0a7c932015-04-09 09:24:48 +02002003 BluetoothServerSocket socket = new BluetoothServerSocket(
Casper Bonde91276012015-05-08 14:32:24 +02002004 BluetoothSocket.TYPE_L2CAP, true, true, port, mitm, min16DigitPin);
Casper Bondec0a7c932015-04-09 09:24:48 +02002005 int errno = socket.mSocket.bindListen();
Jack He910201b2017-08-22 16:06:54 -07002006 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bondec0a7c932015-04-09 09:24:48 +02002007 socket.setChannel(socket.mSocket.getPort());
2008 }
2009 if (errno != 0) {
2010 //TODO(BT): Throw the same exception error code
2011 // that the previous code was using.
2012 //socket.mSocket.throwErrnoNative(errno);
2013 throw new IOException("Error: " + errno);
2014 }
2015 return socket;
2016 }
2017
2018 /**
Casper Bonde60d77c22015-04-21 13:12:05 +02002019 * Construct an encrypted, authenticated, L2CAP server socket.
2020 * Call #accept to retrieve connections to this socket.
2021 * <p>To auto assign a port without creating a SDP record use
2022 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack He910201b2017-08-22 16:06:54 -07002023 *
2024 * @param port the PSM to listen on
Casper Bonde60d77c22015-04-21 13:12:05 +02002025 * @return An L2CAP BluetoothServerSocket
Jack He910201b2017-08-22 16:06:54 -07002026 * @throws IOException On error, for example Bluetooth not available, or insufficient
2027 * permissions.
Casper Bonde60d77c22015-04-21 13:12:05 +02002028 * @hide
2029 */
2030 public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
Casper Bonde91276012015-05-08 14:32:24 +02002031 return listenUsingL2capOn(port, false, false);
Casper Bonde60d77c22015-04-21 13:12:05 +02002032 }
2033
Hemant Gupta0849d402017-02-03 16:38:59 +05302034
2035 /**
2036 * Construct an insecure L2CAP server socket.
2037 * Call #accept to retrieve connections to this socket.
2038 * <p>To auto assign a port without creating a SDP record use
2039 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack He910201b2017-08-22 16:06:54 -07002040 *
2041 * @param port the PSM to listen on
Hemant Gupta0849d402017-02-03 16:38:59 +05302042 * @return An L2CAP BluetoothServerSocket
Jack He910201b2017-08-22 16:06:54 -07002043 * @throws IOException On error, for example Bluetooth not available, or insufficient
2044 * permissions.
Hemant Gupta0849d402017-02-03 16:38:59 +05302045 * @hide
2046 */
2047 public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
2048 BluetoothServerSocket socket = new BluetoothServerSocket(
2049 BluetoothSocket.TYPE_L2CAP, false, false, port, false, false);
2050 int errno = socket.mSocket.bindListen();
Jack He910201b2017-08-22 16:06:54 -07002051 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Hemant Gupta0849d402017-02-03 16:38:59 +05302052 socket.setChannel(socket.mSocket.getPort());
2053 }
2054 if (errno != 0) {
2055 //TODO(BT): Throw the same exception error code
2056 // that the previous code was using.
2057 //socket.mSocket.throwErrnoNative(errno);
2058 throw new IOException("Error: " + errno);
2059 }
2060 return socket;
2061
2062 }
2063
Casper Bonde60d77c22015-04-21 13:12:05 +02002064 /**
Jaikumar Ganesh76965ca2010-09-09 15:37:57 -07002065 * Read the local Out of Band Pairing Data
2066 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
2067 *
2068 * @return Pair<byte[], byte[]> of Hash and Randomizer
Jaikumar Ganesh76965ca2010-09-09 15:37:57 -07002069 * @hide
2070 */
2071 public Pair<byte[], byte[]> readOutOfBandData() {
Jaikumar Ganesh76965ca2010-09-09 15:37:57 -07002072 return null;
2073 }
2074
Scott Main4883a572011-01-19 21:13:18 -08002075 /**
Jaikumar Ganesh2af07762010-08-24 17:36:13 -07002076 * Get the profile proxy object associated with the profile.
2077 *
Ganesh Ganapathi Batta40b98952013-02-05 15:28:33 -08002078 * <p>Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
Matthew Xie9afa2742013-03-01 18:41:02 -08002079 * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, or
2080 * {@link BluetoothProfile#GATT_SERVER}. Clients must implement
Jaikumar Ganesh2af07762010-08-24 17:36:13 -07002081 * {@link BluetoothProfile.ServiceListener} to get notified of
2082 * the connection status and to get the proxy object.
2083 *
2084 * @param context Context of the application
2085 * @param listener The service Listener for connection callbacks.
Jack He910201b2017-08-22 16:06:54 -07002086 * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH}, {@link
2087 * BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}. {@link BluetoothProfile#GATT} or
2088 * {@link BluetoothProfile#GATT_SERVER}.
Jaikumar Ganesh2af07762010-08-24 17:36:13 -07002089 * @return true on success, false on error
2090 */
2091 public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
Jack He910201b2017-08-22 16:06:54 -07002092 int profile) {
Jaikumar Ganesh2af07762010-08-24 17:36:13 -07002093 if (context == null || listener == null) return false;
2094
2095 if (profile == BluetoothProfile.HEADSET) {
2096 BluetoothHeadset headset = new BluetoothHeadset(context, listener);
2097 return true;
2098 } else if (profile == BluetoothProfile.A2DP) {
2099 BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
2100 return true;
Mike Lockwoodf0de5082014-05-14 09:51:30 -07002101 } else if (profile == BluetoothProfile.A2DP_SINK) {
2102 BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
2103 return true;
Mike Lockwood517b04f2014-06-02 16:20:37 -07002104 } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
2105 BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
2106 return true;
Hansong Zhangf0761582017-10-20 15:55:59 -07002107 } else if (profile == BluetoothProfile.HID_HOST) {
2108 BluetoothHidHost iDev = new BluetoothHidHost(context, listener);
Jaikumar Ganeshad5d9c02011-02-18 14:52:32 -08002109 return true;
Jaikumar Ganesh97f8ec42011-02-23 10:22:15 -08002110 } else if (profile == BluetoothProfile.PAN) {
2111 BluetoothPan pan = new BluetoothPan(context, listener);
2112 return true;
Jaikumar Ganeshbf981ca2011-04-01 16:33:09 -07002113 } else if (profile == BluetoothProfile.HEALTH) {
2114 BluetoothHealth health = new BluetoothHealth(context, listener);
2115 return true;
Kim Schulz6816ee22013-08-22 11:18:02 +02002116 } else if (profile == BluetoothProfile.MAP) {
2117 BluetoothMap map = new BluetoothMap(context, listener);
2118 return true;
Mike Lockwoodf48a7272014-06-12 11:23:40 -07002119 } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
2120 BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
Hemant Gupta67a995a2013-08-19 19:03:51 +05302121 return true;
Casper Bonded8355fb2015-03-19 10:36:45 +01002122 } else if (profile == BluetoothProfile.SAP) {
2123 BluetoothSap sap = new BluetoothSap(context, listener);
2124 return true;
Joseph Pirozzo6f56b0f2016-03-04 13:02:54 -08002125 } else if (profile == BluetoothProfile.PBAP_CLIENT) {
2126 BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
2127 return true;
Joseph Pirozzo54d4b662016-09-01 14:19:28 -07002128 } else if (profile == BluetoothProfile.MAP_CLIENT) {
2129 BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
2130 return true;
Hansong Zhangf0761582017-10-20 15:55:59 -07002131 } else if (profile == BluetoothProfile.HID_DEVICE) {
2132 BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener);
Ivan Podogovb6e4b122016-12-30 14:35:09 +00002133 return true;
Jaikumar Ganesh2af07762010-08-24 17:36:13 -07002134 } else {
2135 return false;
2136 }
2137 }
2138
2139 /**
2140 * Close the connection of the profile proxy to the Service.
2141 *
2142 * <p> Clients should call this when they are no longer using
2143 * the proxy obtained from {@link #getProfileProxy}.
Scott Main3c0c5be2011-09-26 22:59:38 -07002144 * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET} or
Jaikumar Ganesh2af07762010-08-24 17:36:13 -07002145 * {@link BluetoothProfile#A2DP}
2146 *
2147 * @param profile
2148 * @param proxy Profile proxy object
2149 */
2150 public void closeProfileProxy(int profile, BluetoothProfile proxy) {
Jaikumar Ganesh05180ed2011-11-28 09:59:08 -08002151 if (proxy == null) return;
2152
2153 switch (profile) {
2154 case BluetoothProfile.HEADSET:
Jack He910201b2017-08-22 16:06:54 -07002155 BluetoothHeadset headset = (BluetoothHeadset) proxy;
Jaikumar Ganesh2af07762010-08-24 17:36:13 -07002156 headset.close();
Jaikumar Ganesh05180ed2011-11-28 09:59:08 -08002157 break;
2158 case BluetoothProfile.A2DP:
Jack He910201b2017-08-22 16:06:54 -07002159 BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
Jaikumar Ganesh05180ed2011-11-28 09:59:08 -08002160 a2dp.close();
2161 break;
Mike Lockwoodf0de5082014-05-14 09:51:30 -07002162 case BluetoothProfile.A2DP_SINK:
Jack He910201b2017-08-22 16:06:54 -07002163 BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink) proxy;
Mike Lockwoodf0de5082014-05-14 09:51:30 -07002164 a2dpSink.close();
2165 break;
Mike Lockwood517b04f2014-06-02 16:20:37 -07002166 case BluetoothProfile.AVRCP_CONTROLLER:
Jack He910201b2017-08-22 16:06:54 -07002167 BluetoothAvrcpController avrcp = (BluetoothAvrcpController) proxy;
Mike Lockwood517b04f2014-06-02 16:20:37 -07002168 avrcp.close();
2169 break;
Hansong Zhangf0761582017-10-20 15:55:59 -07002170 case BluetoothProfile.HID_HOST:
2171 BluetoothHidHost iDev = (BluetoothHidHost) proxy;
Jaikumar Ganesh05180ed2011-11-28 09:59:08 -08002172 iDev.close();
2173 break;
2174 case BluetoothProfile.PAN:
Jack He910201b2017-08-22 16:06:54 -07002175 BluetoothPan pan = (BluetoothPan) proxy;
Jaikumar Ganesh05180ed2011-11-28 09:59:08 -08002176 pan.close();
2177 break;
2178 case BluetoothProfile.HEALTH:
Jack He910201b2017-08-22 16:06:54 -07002179 BluetoothHealth health = (BluetoothHealth) proxy;
Jaikumar Ganesh05180ed2011-11-28 09:59:08 -08002180 health.close();
2181 break;
Jack He910201b2017-08-22 16:06:54 -07002182 case BluetoothProfile.GATT:
2183 BluetoothGatt gatt = (BluetoothGatt) proxy;
Ganesh Ganapathi Batta40b98952013-02-05 15:28:33 -08002184 gatt.close();
2185 break;
2186 case BluetoothProfile.GATT_SERVER:
Jack He910201b2017-08-22 16:06:54 -07002187 BluetoothGattServer gattServer = (BluetoothGattServer) proxy;
Ganesh Ganapathi Batta40b98952013-02-05 15:28:33 -08002188 gattServer.close();
2189 break;
Kim Schulz6816ee22013-08-22 11:18:02 +02002190 case BluetoothProfile.MAP:
Jack He910201b2017-08-22 16:06:54 -07002191 BluetoothMap map = (BluetoothMap) proxy;
Kim Schulz6816ee22013-08-22 11:18:02 +02002192 map.close();
2193 break;
Mike Lockwoodf48a7272014-06-12 11:23:40 -07002194 case BluetoothProfile.HEADSET_CLIENT:
Jack He910201b2017-08-22 16:06:54 -07002195 BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient) proxy;
Mike Lockwoodf48a7272014-06-12 11:23:40 -07002196 headsetClient.close();
Hemant Gupta67a995a2013-08-19 19:03:51 +05302197 break;
Casper Bonded8355fb2015-03-19 10:36:45 +01002198 case BluetoothProfile.SAP:
Jack He910201b2017-08-22 16:06:54 -07002199 BluetoothSap sap = (BluetoothSap) proxy;
Casper Bonded8355fb2015-03-19 10:36:45 +01002200 sap.close();
2201 break;
Joseph Pirozzo6f56b0f2016-03-04 13:02:54 -08002202 case BluetoothProfile.PBAP_CLIENT:
Jack He910201b2017-08-22 16:06:54 -07002203 BluetoothPbapClient pbapClient = (BluetoothPbapClient) proxy;
Joseph Pirozzo6f56b0f2016-03-04 13:02:54 -08002204 pbapClient.close();
2205 break;
Joseph Pirozzo54d4b662016-09-01 14:19:28 -07002206 case BluetoothProfile.MAP_CLIENT:
Jack He910201b2017-08-22 16:06:54 -07002207 BluetoothMapClient mapClient = (BluetoothMapClient) proxy;
Joseph Pirozzo54d4b662016-09-01 14:19:28 -07002208 mapClient.close();
2209 break;
Hansong Zhangf0761582017-10-20 15:55:59 -07002210 case BluetoothProfile.HID_DEVICE:
2211 BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy;
2212 hidDevice.close();
Ivan Podogovb6e4b122016-12-30 14:35:09 +00002213 break;
Jaikumar Ganesh2af07762010-08-24 17:36:13 -07002214 }
2215 }
2216
Jack He9e045d22017-08-22 21:21:23 -07002217 private final IBluetoothManagerCallback mManagerCallback =
Jack He910201b2017-08-22 16:06:54 -07002218 new IBluetoothManagerCallback.Stub() {
2219 public void onBluetoothServiceUp(IBluetooth bluetoothService) {
2220 if (DBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07002221
Pavlin Radoslavov630c0a32016-05-24 15:28:41 -07002222 mServiceLock.writeLock().lock();
Jack He910201b2017-08-22 16:06:54 -07002223 mService = bluetoothService;
Pavlin Radoslavov630c0a32016-05-24 15:28:41 -07002224 mServiceLock.writeLock().unlock();
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07002225
Jack He910201b2017-08-22 16:06:54 -07002226 synchronized (mProxyServiceStateCallbacks) {
2227 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
2228 try {
2229 if (cb != null) {
2230 cb.onBluetoothServiceUp(bluetoothService);
2231 } else {
2232 Log.d(TAG, "onBluetoothServiceUp: cb is null!");
2233 }
2234 } catch (Exception e) {
2235 Log.e(TAG, "", e);
Pavlin Radoslavov6d126c82016-05-22 22:16:41 -07002236 }
Matthew Xieb6600692015-02-06 14:09:54 -08002237 }
fredcf1f5dde2012-04-24 03:59:57 -07002238 }
fredc3c719642012-04-12 00:02:00 -07002239 }
Nitin Arora7688f222015-03-02 15:03:51 -08002240
Jack He910201b2017-08-22 16:06:54 -07002241 public void onBluetoothServiceDown() {
2242 if (DBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
2243
2244 try {
2245 mServiceLock.writeLock().lock();
2246 mService = null;
2247 if (mLeScanClients != null) mLeScanClients.clear();
2248 if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup();
2249 if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup();
2250 } finally {
2251 mServiceLock.writeLock().unlock();
2252 }
2253
2254 synchronized (mProxyServiceStateCallbacks) {
2255 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
2256 try {
2257 if (cb != null) {
2258 cb.onBluetoothServiceDown();
2259 } else {
2260 Log.d(TAG, "onBluetoothServiceDown: cb is null!");
2261 }
2262 } catch (Exception e) {
2263 Log.e(TAG, "", e);
2264 }
2265 }
2266 }
2267 }
2268
2269 public void onBrEdrDown() {
2270 if (VDBG) Log.i(TAG, "onBrEdrDown: " + mService);
2271 }
2272 };
fredc3c719642012-04-12 00:02:00 -07002273
Jaikumar Ganeshcb4d9682011-07-21 18:13:38 -07002274 /**
Martijn Coenena9110b82012-04-18 13:01:15 -07002275 * Enable the Bluetooth Adapter, but don't auto-connect devices
2276 * and don't persist state. Only for use by system applications.
Jack He910201b2017-08-22 16:06:54 -07002277 *
Martijn Coenena9110b82012-04-18 13:01:15 -07002278 * @hide
2279 */
2280 public boolean enableNoAutoConnect() {
Jack He9e045d22017-08-22 21:21:23 -07002281 if (isEnabled()) {
Marie Janssenf46373a2016-12-13 10:51:02 -08002282 if (DBG) Log.d(TAG, "enableNoAutoConnect(): BT already enabled!");
Ganesh Ganapathi Battafa1a5272012-08-08 15:35:49 -07002283 return true;
2284 }
2285 try {
Marie Janssen6eb20462016-12-28 14:13:21 -08002286 return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName());
Jack He910201b2017-08-22 16:06:54 -07002287 } catch (RemoteException e) {
2288 Log.e(TAG, "", e);
2289 }
Ganesh Ganapathi Battafa1a5272012-08-08 15:35:49 -07002290 return false;
Martijn Coenena9110b82012-04-18 13:01:15 -07002291 }
2292
2293 /**
Jaikumar Ganeshcb4d9682011-07-21 18:13:38 -07002294 * Enable control of the Bluetooth Adapter for a single application.
2295 *
2296 * <p>Some applications need to use Bluetooth for short periods of time to
2297 * transfer data but don't want all the associated implications like
2298 * automatic connection to headsets etc.
2299 *
2300 * <p> Multiple applications can call this. This is reference counted and
2301 * Bluetooth disabled only when no one else is using it. There will be no UI
2302 * shown to the user while bluetooth is being enabled. Any user action will
2303 * override this call. For example, if user wants Bluetooth on and the last
2304 * user of this API wanted to disable Bluetooth, Bluetooth will not be
2305 * turned off.
2306 *
2307 * <p> This API is only meant to be used by internal applications. Third
2308 * party applications but use {@link #enable} and {@link #disable} APIs.
2309 *
2310 * <p> If this API returns true, it means the callback will be called.
2311 * The callback will be called with the current state of Bluetooth.
2312 * If the state is not what was requested, an internal error would be the
Jaikumar Ganesha13f8e82011-08-03 14:17:22 -07002313 * reason. If Bluetooth is already on and if this function is called to turn
2314 * it on, the api will return true and a callback will be called.
2315 *
2316 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Jaikumar Ganeshcb4d9682011-07-21 18:13:38 -07002317 *
2318 * @param on True for on, false for off.
2319 * @param callback The callback to notify changes to the state.
2320 * @hide
2321 */
2322 public boolean changeApplicationBluetoothState(boolean on,
Jack He910201b2017-08-22 16:06:54 -07002323 BluetoothStateChangeCallback callback) {
Jaikumar Ganeshcb4d9682011-07-21 18:13:38 -07002324 return false;
2325 }
2326
2327 /**
2328 * @hide
2329 */
2330 public interface BluetoothStateChangeCallback {
2331 public void onBluetoothStateChange(boolean on);
2332 }
2333
2334 /**
2335 * @hide
2336 */
2337 public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
2338 private BluetoothStateChangeCallback mCallback;
2339
2340 StateChangeCallbackWrapper(BluetoothStateChangeCallback
2341 callback) {
2342 mCallback = callback;
2343 }
2344
2345 @Override
2346 public void onBluetoothStateChange(boolean on) {
2347 mCallback.onBluetoothStateChange(on);
2348 }
2349 }
2350
Jaikumar Ganesh88445232012-01-25 16:16:48 -08002351 private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
2352 Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
2353 return Collections.unmodifiableSet(deviceSet);
Nick Pelly2d664882009-08-14 18:33:38 -07002354 }
Nick Pellydac4c0d2009-09-10 10:21:56 -07002355
fredc3c719642012-04-12 00:02:00 -07002356 protected void finalize() throws Throwable {
2357 try {
2358 mManagerService.unregisterAdapter(mManagerCallback);
2359 } catch (RemoteException e) {
2360 Log.e(TAG, "", e);
2361 } finally {
2362 super.finalize();
2363 }
2364 }
2365
2366
Nick Pellydac4c0d2009-09-10 10:21:56 -07002367 /**
Nick Pellyd3fca952011-12-07 15:03:55 -08002368 * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
Nick Pelly6ef935c2009-09-18 11:37:06 -07002369 * <p>Alphabetic characters must be uppercase to be valid.
Nick Pellydac4c0d2009-09-10 10:21:56 -07002370 *
2371 * @param address Bluetooth address as string
2372 * @return true if the address is valid, false otherwise
2373 */
2374 public static boolean checkBluetoothAddress(String address) {
2375 if (address == null || address.length() != ADDRESS_LENGTH) {
2376 return false;
2377 }
2378 for (int i = 0; i < ADDRESS_LENGTH; i++) {
2379 char c = address.charAt(i);
2380 switch (i % 3) {
Jack He910201b2017-08-22 16:06:54 -07002381 case 0:
2382 case 1:
2383 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
2384 // hex character, OK
2385 break;
2386 }
2387 return false;
2388 case 2:
2389 if (c == ':') {
2390 break; // OK
2391 }
2392 return false;
Nick Pellydac4c0d2009-09-10 10:21:56 -07002393 }
2394 }
2395 return true;
2396 }
fredc3c719642012-04-12 00:02:00 -07002397
2398 /*package*/ IBluetoothManager getBluetoothManager() {
Jack He910201b2017-08-22 16:06:54 -07002399 return mManagerService;
fredc3c719642012-04-12 00:02:00 -07002400 }
2401
Jack He9e045d22017-08-22 21:21:23 -07002402 private final ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks =
Jack He910201b2017-08-22 16:06:54 -07002403 new ArrayList<IBluetoothManagerCallback>();
fredce8d15192012-04-25 17:46:13 -07002404
fredcf1f5dde2012-04-24 03:59:57 -07002405 /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
Matthew Xieb6600692015-02-06 14:09:54 -08002406 synchronized (mProxyServiceStateCallbacks) {
fredce8d15192012-04-25 17:46:13 -07002407 if (cb == null) {
fredcd07368a2012-05-09 16:52:50 -07002408 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
2409 } else if (!mProxyServiceStateCallbacks.contains(cb)) {
2410 mProxyServiceStateCallbacks.add(cb);
fredcf1f5dde2012-04-24 03:59:57 -07002411 }
2412 }
2413 return mService;
2414 }
2415
2416 /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
Matthew Xieb6600692015-02-06 14:09:54 -08002417 synchronized (mProxyServiceStateCallbacks) {
fredcd07368a2012-05-09 16:52:50 -07002418 mProxyServiceStateCallbacks.remove(cb);
fredc3c719642012-04-12 00:02:00 -07002419 }
2420 }
Matthew Xie9afa2742013-03-01 18:41:02 -08002421
2422 /**
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002423 * Callback interface used to deliver LE scan results.
Matthew Xie9afa2742013-03-01 18:41:02 -08002424 *
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002425 * @see #startLeScan(LeScanCallback)
2426 * @see #startLeScan(UUID[], LeScanCallback)
Matthew Xie9afa2742013-03-01 18:41:02 -08002427 */
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002428 public interface LeScanCallback {
2429 /**
2430 * Callback reporting an LE device found during a device scan initiated
2431 * by the {@link BluetoothAdapter#startLeScan} function.
2432 *
2433 * @param device Identifies the remote device
Jack He910201b2017-08-22 16:06:54 -07002434 * @param rssi The RSSI value for the remote device as reported by the Bluetooth hardware. 0
2435 * if no RSSI value is available.
2436 * @param scanRecord The content of the advertisement record offered by the remote device.
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002437 */
2438 public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
Matthew Xie9afa2742013-03-01 18:41:02 -08002439 }
2440
2441 /**
2442 * Starts a scan for Bluetooth LE devices.
2443 *
2444 * <p>Results of the scan are reported using the
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002445 * {@link LeScanCallback#onLeScan} callback.
Matthew Xie9afa2742013-03-01 18:41:02 -08002446 *
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002447 * @param callback the callback LE scan results are delivered
Matthew Xie9afa2742013-03-01 18:41:02 -08002448 * @return true, if the scan was started successfully
Wei Wang7faed2f2014-07-09 14:03:42 -07002449 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
Jack He910201b2017-08-22 16:06:54 -07002450 * instead.
Matthew Xie9afa2742013-03-01 18:41:02 -08002451 */
Wei Wang7faed2f2014-07-09 14:03:42 -07002452 @Deprecated
Tor Norbye27ce6cf2015-04-23 17:10:21 -07002453 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002454 public boolean startLeScan(LeScanCallback callback) {
2455 return startLeScan(null, callback);
Matthew Xie9afa2742013-03-01 18:41:02 -08002456 }
2457
2458 /**
2459 * Starts a scan for Bluetooth LE devices, looking for devices that
2460 * advertise given services.
2461 *
2462 * <p>Devices which advertise all specified services are reported using the
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002463 * {@link LeScanCallback#onLeScan} callback.
Matthew Xie9afa2742013-03-01 18:41:02 -08002464 *
Matthew Xie9afa2742013-03-01 18:41:02 -08002465 * @param serviceUuids Array of services to look for
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002466 * @param callback the callback LE scan results are delivered
Matthew Xie9afa2742013-03-01 18:41:02 -08002467 * @return true, if the scan was started successfully
Wei Wang7faed2f2014-07-09 14:03:42 -07002468 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
Jack He910201b2017-08-22 16:06:54 -07002469 * instead.
Matthew Xie9afa2742013-03-01 18:41:02 -08002470 */
Wei Wang7faed2f2014-07-09 14:03:42 -07002471 @Deprecated
Tor Norbye27ce6cf2015-04-23 17:10:21 -07002472 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Wei Wang4c2da322014-07-23 23:34:00 -07002473 public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
Andreas Gampe7b1e7402015-12-11 18:00:38 -08002474 if (DBG) Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002475 if (callback == null) {
2476 if (DBG) Log.e(TAG, "startLeScan: null callback");
Matthew Xie9afa2742013-03-01 18:41:02 -08002477 return false;
2478 }
Wei Wang4c2da322014-07-23 23:34:00 -07002479 BluetoothLeScanner scanner = getBluetoothLeScanner();
2480 if (scanner == null) {
2481 if (DBG) Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
2482 return false;
2483 }
Matthew Xie9afa2742013-03-01 18:41:02 -08002484
Jack He910201b2017-08-22 16:06:54 -07002485 synchronized (mLeScanClients) {
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002486 if (mLeScanClients.containsKey(callback)) {
2487 if (DBG) Log.e(TAG, "LE Scan has already started");
2488 return false;
2489 }
2490
2491 try {
2492 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
Matthew Xiec3ef4fc2013-05-08 19:26:57 -07002493 if (iGatt == null) {
2494 // BLE is not supported
2495 return false;
2496 }
2497
Wei Wang4c2da322014-07-23 23:34:00 -07002498 ScanCallback scanCallback = new ScanCallback() {
2499 @Override
2500 public void onScanResult(int callbackType, ScanResult result) {
2501 if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
2502 // Should not happen.
2503 Log.e(TAG, "LE Scan has already started");
2504 return;
2505 }
2506 ScanRecord scanRecord = result.getScanRecord();
2507 if (scanRecord == null) {
2508 return;
2509 }
2510 if (serviceUuids != null) {
2511 List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
2512 for (UUID uuid : serviceUuids) {
2513 uuids.add(new ParcelUuid(uuid));
2514 }
2515 List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
2516 if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
2517 if (DBG) Log.d(TAG, "uuids does not match");
2518 return;
2519 }
2520 }
2521 callback.onLeScan(result.getDevice(), result.getRssi(),
2522 scanRecord.getBytes());
2523 }
2524 };
2525 ScanSettings settings = new ScanSettings.Builder()
Jack He910201b2017-08-22 16:06:54 -07002526 .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
2527 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
Wei Wang4c2da322014-07-23 23:34:00 -07002528
2529 List<ScanFilter> filters = new ArrayList<ScanFilter>();
2530 if (serviceUuids != null && serviceUuids.length > 0) {
2531 // Note scan filter does not support matching an UUID array so we put one
2532 // UUID to hardware and match the whole array in callback.
2533 ScanFilter filter = new ScanFilter.Builder().setServiceUuid(
2534 new ParcelUuid(serviceUuids[0])).build();
2535 filters.add(filter);
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002536 }
Wei Wang4c2da322014-07-23 23:34:00 -07002537 scanner.startScan(filters, settings, scanCallback);
2538
2539 mLeScanClients.put(callback, scanCallback);
2540 return true;
2541
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002542 } catch (RemoteException e) {
Jack He910201b2017-08-22 16:06:54 -07002543 Log.e(TAG, "", e);
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002544 }
2545 }
2546 return false;
Matthew Xie9afa2742013-03-01 18:41:02 -08002547 }
2548
2549 /**
2550 * Stops an ongoing Bluetooth LE device scan.
2551 *
Jack He910201b2017-08-22 16:06:54 -07002552 * @param callback used to identify which scan to stop must be the same handle used to start the
2553 * scan
Wei Wang7faed2f2014-07-09 14:03:42 -07002554 * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
Matthew Xie9afa2742013-03-01 18:41:02 -08002555 */
Wei Wang7faed2f2014-07-09 14:03:42 -07002556 @Deprecated
Tor Norbye27ce6cf2015-04-23 17:10:21 -07002557 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002558 public void stopLeScan(LeScanCallback callback) {
2559 if (DBG) Log.d(TAG, "stopLeScan()");
Wei Wang4c2da322014-07-23 23:34:00 -07002560 BluetoothLeScanner scanner = getBluetoothLeScanner();
2561 if (scanner == null) {
2562 return;
Matthew Xie9afa2742013-03-01 18:41:02 -08002563 }
Wei Wang4c2da322014-07-23 23:34:00 -07002564 synchronized (mLeScanClients) {
2565 ScanCallback scanCallback = mLeScanClients.remove(callback);
2566 if (scanCallback == null) {
2567 if (DBG) Log.d(TAG, "scan not started yet");
2568 return;
Matthew Xie9afa2742013-03-01 18:41:02 -08002569 }
Wei Wang4c2da322014-07-23 23:34:00 -07002570 scanner.stopScan(scanCallback);
Prerepa Viswanadham5daedc12014-07-09 12:51:59 -07002571 }
Matthew Xie01e8e2a2013-04-11 16:36:26 -07002572 }
Nick Pelly2d664882009-08-14 18:33:38 -07002573}