blob: 504118ec5da8b783f54c126651fa29d4facf26d0 [file] [log] [blame]
Alan Viverette3da604b2020-06-10 18:34:39 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.bluetooth.le;
18
19import android.annotation.SystemApi;
20import android.bluetooth.BluetoothDevice;
21import android.os.Parcel;
22import android.os.Parcelable;
23
24/**
25 * Bluetooth LE scan settings are passed to {@link BluetoothLeScanner#startScan} to define the
26 * parameters for the scan.
27 */
28public final class ScanSettings implements Parcelable {
29
30 /**
31 * A special Bluetooth LE scan mode. Applications using this scan mode will passively listen for
32 * other scan results without starting BLE scans themselves.
33 */
34 public static final int SCAN_MODE_OPPORTUNISTIC = -1;
35
36 /**
37 * Perform Bluetooth LE scan in low power mode. This is the default scan mode as it consumes the
38 * least power. This mode is enforced if the scanning application is not in foreground.
39 */
40 public static final int SCAN_MODE_LOW_POWER = 0;
41
42 /**
43 * Perform Bluetooth LE scan in balanced power mode. Scan results are returned at a rate that
44 * provides a good trade-off between scan frequency and power consumption.
45 */
46 public static final int SCAN_MODE_BALANCED = 1;
47
48 /**
49 * Scan using highest duty cycle. It's recommended to only use this mode when the application is
50 * running in the foreground.
51 */
52 public static final int SCAN_MODE_LOW_LATENCY = 2;
53
54 /**
55 * Trigger a callback for every Bluetooth advertisement found that matches the filter criteria.
56 * If no filter is active, all advertisement packets are reported.
57 */
58 public static final int CALLBACK_TYPE_ALL_MATCHES = 1;
59
60 /**
61 * A result callback is only triggered for the first advertisement packet received that matches
62 * the filter criteria.
63 */
64 public static final int CALLBACK_TYPE_FIRST_MATCH = 2;
65
66 /**
67 * Receive a callback when advertisements are no longer received from a device that has been
68 * previously reported by a first match callback.
69 */
70 public static final int CALLBACK_TYPE_MATCH_LOST = 4;
71
72
73 /**
74 * Determines how many advertisements to match per filter, as this is scarce hw resource
75 */
76 /**
77 * Match one advertisement per filter
78 */
79 public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1;
80
81 /**
82 * Match few advertisement per filter, depends on current capability and availibility of
83 * the resources in hw
84 */
85 public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2;
86
87 /**
88 * Match as many advertisement per filter as hw could allow, depends on current
89 * capability and availibility of the resources in hw
90 */
91 public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3;
92
93
94 /**
95 * In Aggressive mode, hw will determine a match sooner even with feeble signal strength
96 * and few number of sightings/match in a duration.
97 */
98 public static final int MATCH_MODE_AGGRESSIVE = 1;
99
100 /**
101 * For sticky mode, higher threshold of signal strength and sightings is required
102 * before reporting by hw
103 */
104 public static final int MATCH_MODE_STICKY = 2;
105
106 /**
107 * Request full scan results which contain the device, rssi, advertising data, scan response
108 * as well as the scan timestamp.
109 *
110 * @hide
111 */
112 @SystemApi
113 public static final int SCAN_RESULT_TYPE_FULL = 0;
114
115 /**
116 * Request abbreviated scan results which contain the device, rssi and scan timestamp.
117 * <p>
118 * <b>Note:</b> It is possible for an application to get more scan results than it asked for, if
119 * there are multiple apps using this type.
120 *
121 * @hide
122 */
123 @SystemApi
124 public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1;
125
126 /**
127 * Use all supported PHYs for scanning.
128 * This will check the controller capabilities, and start
129 * the scan on 1Mbit and LE Coded PHYs if supported, or on
130 * the 1Mbit PHY only.
131 */
132 public static final int PHY_LE_ALL_SUPPORTED = 255;
133
134 // Bluetooth LE scan mode.
135 private int mScanMode;
136
137 // Bluetooth LE scan callback type
138 private int mCallbackType;
139
140 // Bluetooth LE scan result type
141 private int mScanResultType;
142
143 // Time of delay for reporting the scan result
144 private long mReportDelayMillis;
145
146 private int mMatchMode;
147
148 private int mNumOfMatchesPerFilter;
149
150 // Include only legacy advertising results
151 private boolean mLegacy;
152
153 private int mPhy;
154
155 public int getScanMode() {
156 return mScanMode;
157 }
158
159 public int getCallbackType() {
160 return mCallbackType;
161 }
162
163 public int getScanResultType() {
164 return mScanResultType;
165 }
166
167 /**
168 * @hide
169 */
170 public int getMatchMode() {
171 return mMatchMode;
172 }
173
174 /**
175 * @hide
176 */
177 public int getNumOfMatches() {
178 return mNumOfMatchesPerFilter;
179 }
180
181 /**
182 * Returns whether only legacy advertisements will be returned.
183 * Legacy advertisements include advertisements as specified
184 * by the Bluetooth core specification 4.2 and below.
185 */
186 public boolean getLegacy() {
187 return mLegacy;
188 }
189
190 /**
191 * Returns the physical layer used during a scan.
192 */
193 public int getPhy() {
194 return mPhy;
195 }
196
197 /**
198 * Returns report delay timestamp based on the device clock.
199 */
200 public long getReportDelayMillis() {
201 return mReportDelayMillis;
202 }
203
204 private ScanSettings(int scanMode, int callbackType, int scanResultType,
205 long reportDelayMillis, int matchMode,
206 int numOfMatchesPerFilter, boolean legacy, int phy) {
207 mScanMode = scanMode;
208 mCallbackType = callbackType;
209 mScanResultType = scanResultType;
210 mReportDelayMillis = reportDelayMillis;
211 mNumOfMatchesPerFilter = numOfMatchesPerFilter;
212 mMatchMode = matchMode;
213 mLegacy = legacy;
214 mPhy = phy;
215 }
216
217 private ScanSettings(Parcel in) {
218 mScanMode = in.readInt();
219 mCallbackType = in.readInt();
220 mScanResultType = in.readInt();
221 mReportDelayMillis = in.readLong();
222 mMatchMode = in.readInt();
223 mNumOfMatchesPerFilter = in.readInt();
224 mLegacy = in.readInt() != 0;
225 mPhy = in.readInt();
226 }
227
228 @Override
229 public void writeToParcel(Parcel dest, int flags) {
230 dest.writeInt(mScanMode);
231 dest.writeInt(mCallbackType);
232 dest.writeInt(mScanResultType);
233 dest.writeLong(mReportDelayMillis);
234 dest.writeInt(mMatchMode);
235 dest.writeInt(mNumOfMatchesPerFilter);
236 dest.writeInt(mLegacy ? 1 : 0);
237 dest.writeInt(mPhy);
238 }
239
240 @Override
241 public int describeContents() {
242 return 0;
243 }
244
245 public static final @android.annotation.NonNull Parcelable.Creator<ScanSettings> CREATOR =
246 new Creator<ScanSettings>() {
247 @Override
248 public ScanSettings[] newArray(int size) {
249 return new ScanSettings[size];
250 }
251
252 @Override
253 public ScanSettings createFromParcel(Parcel in) {
254 return new ScanSettings(in);
255 }
256 };
257
258 /**
259 * Builder for {@link ScanSettings}.
260 */
261 public static final class Builder {
262 private int mScanMode = SCAN_MODE_LOW_POWER;
263 private int mCallbackType = CALLBACK_TYPE_ALL_MATCHES;
264 private int mScanResultType = SCAN_RESULT_TYPE_FULL;
265 private long mReportDelayMillis = 0;
266 private int mMatchMode = MATCH_MODE_AGGRESSIVE;
267 private int mNumOfMatchesPerFilter = MATCH_NUM_MAX_ADVERTISEMENT;
268 private boolean mLegacy = true;
269 private int mPhy = PHY_LE_ALL_SUPPORTED;
270
271 /**
272 * Set scan mode for Bluetooth LE scan.
273 *
274 * @param scanMode The scan mode can be one of {@link ScanSettings#SCAN_MODE_LOW_POWER},
275 * {@link ScanSettings#SCAN_MODE_BALANCED} or {@link ScanSettings#SCAN_MODE_LOW_LATENCY}.
276 * @throws IllegalArgumentException If the {@code scanMode} is invalid.
277 */
278 public Builder setScanMode(int scanMode) {
279 if (scanMode < SCAN_MODE_OPPORTUNISTIC || scanMode > SCAN_MODE_LOW_LATENCY) {
280 throw new IllegalArgumentException("invalid scan mode " + scanMode);
281 }
282 mScanMode = scanMode;
283 return this;
284 }
285
286 /**
287 * Set callback type for Bluetooth LE scan.
288 *
289 * @param callbackType The callback type flags for the scan.
290 * @throws IllegalArgumentException If the {@code callbackType} is invalid.
291 */
292 public Builder setCallbackType(int callbackType) {
293
294 if (!isValidCallbackType(callbackType)) {
295 throw new IllegalArgumentException("invalid callback type - " + callbackType);
296 }
297 mCallbackType = callbackType;
298 return this;
299 }
300
301 // Returns true if the callbackType is valid.
302 private boolean isValidCallbackType(int callbackType) {
303 if (callbackType == CALLBACK_TYPE_ALL_MATCHES
304 || callbackType == CALLBACK_TYPE_FIRST_MATCH
305 || callbackType == CALLBACK_TYPE_MATCH_LOST) {
306 return true;
307 }
308 return callbackType == (CALLBACK_TYPE_FIRST_MATCH | CALLBACK_TYPE_MATCH_LOST);
309 }
310
311 /**
312 * Set scan result type for Bluetooth LE scan.
313 *
314 * @param scanResultType Type for scan result, could be either {@link
315 * ScanSettings#SCAN_RESULT_TYPE_FULL} or {@link ScanSettings#SCAN_RESULT_TYPE_ABBREVIATED}.
316 * @throws IllegalArgumentException If the {@code scanResultType} is invalid.
317 * @hide
318 */
319 @SystemApi
320 public Builder setScanResultType(int scanResultType) {
321 if (scanResultType < SCAN_RESULT_TYPE_FULL
322 || scanResultType > SCAN_RESULT_TYPE_ABBREVIATED) {
323 throw new IllegalArgumentException(
324 "invalid scanResultType - " + scanResultType);
325 }
326 mScanResultType = scanResultType;
327 return this;
328 }
329
330 /**
331 * Set report delay timestamp for Bluetooth LE scan.
332 *
333 * @param reportDelayMillis Delay of report in milliseconds. Set to 0 to be notified of
334 * results immediately. Values &gt; 0 causes the scan results to be queued up and delivered
335 * after the requested delay or when the internal buffers fill up.
336 * @throws IllegalArgumentException If {@code reportDelayMillis} &lt; 0.
337 */
338 public Builder setReportDelay(long reportDelayMillis) {
339 if (reportDelayMillis < 0) {
340 throw new IllegalArgumentException("reportDelay must be > 0");
341 }
342 mReportDelayMillis = reportDelayMillis;
343 return this;
344 }
345
346 /**
347 * Set the number of matches for Bluetooth LE scan filters hardware match
348 *
349 * @param numOfMatches The num of matches can be one of
350 * {@link ScanSettings#MATCH_NUM_ONE_ADVERTISEMENT}
351 * or {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or {@link
352 * ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT}
353 * @throws IllegalArgumentException If the {@code matchMode} is invalid.
354 */
355 public Builder setNumOfMatches(int numOfMatches) {
356 if (numOfMatches < MATCH_NUM_ONE_ADVERTISEMENT
357 || numOfMatches > MATCH_NUM_MAX_ADVERTISEMENT) {
358 throw new IllegalArgumentException("invalid numOfMatches " + numOfMatches);
359 }
360 mNumOfMatchesPerFilter = numOfMatches;
361 return this;
362 }
363
364 /**
365 * Set match mode for Bluetooth LE scan filters hardware match
366 *
367 * @param matchMode The match mode can be one of {@link ScanSettings#MATCH_MODE_AGGRESSIVE}
368 * or {@link ScanSettings#MATCH_MODE_STICKY}
369 * @throws IllegalArgumentException If the {@code matchMode} is invalid.
370 */
371 public Builder setMatchMode(int matchMode) {
372 if (matchMode < MATCH_MODE_AGGRESSIVE
373 || matchMode > MATCH_MODE_STICKY) {
374 throw new IllegalArgumentException("invalid matchMode " + matchMode);
375 }
376 mMatchMode = matchMode;
377 return this;
378 }
379
380 /**
381 * Set whether only legacy advertisments should be returned in scan results.
382 * Legacy advertisements include advertisements as specified by the
383 * Bluetooth core specification 4.2 and below. This is true by default
384 * for compatibility with older apps.
385 *
386 * @param legacy true if only legacy advertisements will be returned
387 */
388 public Builder setLegacy(boolean legacy) {
389 mLegacy = legacy;
390 return this;
391 }
392
393 /**
394 * Set the Physical Layer to use during this scan.
395 * This is used only if {@link ScanSettings.Builder#setLegacy}
396 * is set to false.
397 * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}
398 * may be used to check whether LE Coded phy is supported by calling
399 * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}.
400 * Selecting an unsupported phy will result in failure to start scan.
401 *
402 * @param phy Can be one of {@link BluetoothDevice#PHY_LE_1M}, {@link
403 * BluetoothDevice#PHY_LE_CODED} or {@link ScanSettings#PHY_LE_ALL_SUPPORTED}
404 */
405 public Builder setPhy(int phy) {
406 mPhy = phy;
407 return this;
408 }
409
410 /**
411 * Build {@link ScanSettings}.
412 */
413 public ScanSettings build() {
414 return new ScanSettings(mScanMode, mCallbackType, mScanResultType,
415 mReportDelayMillis, mMatchMode,
416 mNumOfMatchesPerFilter, mLegacy, mPhy);
417 }
418 }
419}