• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.bluetooth.le;
18 
19 import android.annotation.SystemApi;
20 import android.bluetooth.BluetoothDevice;
21 import android.os.Parcel;
22 import 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  */
28 public 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      * Perform Bluetooth LE scan in ambient discovery mode. This mode has lower duty cycle and more
56      * aggressive scan interval than balanced mode that provides a good trade-off between scan
57      * latency and power consumption.
58      *
59      * @hide
60      */
61     @SystemApi
62     public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3;
63 
64     /**
65      * Trigger a callback for every Bluetooth advertisement found that matches the filter criteria.
66      * If no filter is active, all advertisement packets are reported.
67      */
68     public static final int CALLBACK_TYPE_ALL_MATCHES = 1;
69 
70     /**
71      * A result callback is only triggered for the first advertisement packet received that matches
72      * the filter criteria.
73      */
74     public static final int CALLBACK_TYPE_FIRST_MATCH = 2;
75 
76     /**
77      * Receive a callback when advertisements are no longer received from a device that has been
78      * previously reported by a first match callback.
79      */
80     public static final int CALLBACK_TYPE_MATCH_LOST = 4;
81 
82 
83     /**
84      * Determines how many advertisements to match per filter, as this is scarce hw resource
85      */
86     /**
87      * Match one advertisement per filter
88      */
89     public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1;
90 
91     /**
92      * Match few advertisement per filter, depends on current capability and availibility of
93      * the resources in hw
94      */
95     public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2;
96 
97     /**
98      * Match as many advertisement per filter as hw could allow, depends on current
99      * capability and availibility of the resources in hw
100      */
101     public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3;
102 
103 
104     /**
105      * In Aggressive mode, hw will determine a match sooner even with feeble signal strength
106      * and few number of sightings/match in a duration.
107      */
108     public static final int MATCH_MODE_AGGRESSIVE = 1;
109 
110     /**
111      * For sticky mode, higher threshold of signal strength and sightings is required
112      * before reporting by hw
113      */
114     public static final int MATCH_MODE_STICKY = 2;
115 
116     /**
117      * Request full scan results which contain the device, rssi, advertising data, scan response
118      * as well as the scan timestamp.
119      *
120      * @hide
121      */
122     @SystemApi
123     public static final int SCAN_RESULT_TYPE_FULL = 0;
124 
125     /**
126      * Request abbreviated scan results which contain the device, rssi and scan timestamp.
127      * <p>
128      * <b>Note:</b> It is possible for an application to get more scan results than it asked for, if
129      * there are multiple apps using this type.
130      *
131      * @hide
132      */
133     @SystemApi
134     public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1;
135 
136     /**
137      * Use all supported PHYs for scanning.
138      * This will check the controller capabilities, and start
139      * the scan on 1Mbit and LE Coded PHYs if supported, or on
140      * the 1Mbit PHY only.
141      */
142     public static final int PHY_LE_ALL_SUPPORTED = 255;
143 
144     // Bluetooth LE scan mode.
145     private int mScanMode;
146 
147     // Bluetooth LE scan callback type
148     private int mCallbackType;
149 
150     // Bluetooth LE scan result type
151     private int mScanResultType;
152 
153     // Time of delay for reporting the scan result
154     private long mReportDelayMillis;
155 
156     private int mMatchMode;
157 
158     private int mNumOfMatchesPerFilter;
159 
160     // Include only legacy advertising results
161     private boolean mLegacy;
162 
163     private int mPhy;
164 
getScanMode()165     public int getScanMode() {
166         return mScanMode;
167     }
168 
getCallbackType()169     public int getCallbackType() {
170         return mCallbackType;
171     }
172 
getScanResultType()173     public int getScanResultType() {
174         return mScanResultType;
175     }
176 
177     /**
178      * @hide
179      */
getMatchMode()180     public int getMatchMode() {
181         return mMatchMode;
182     }
183 
184     /**
185      * @hide
186      */
getNumOfMatches()187     public int getNumOfMatches() {
188         return mNumOfMatchesPerFilter;
189     }
190 
191     /**
192      * Returns whether only legacy advertisements will be returned.
193      * Legacy advertisements include advertisements as specified
194      * by the Bluetooth core specification 4.2 and below.
195      */
getLegacy()196     public boolean getLegacy() {
197         return mLegacy;
198     }
199 
200     /**
201      * Returns the physical layer used during a scan.
202      */
getPhy()203     public int getPhy() {
204         return mPhy;
205     }
206 
207     /**
208      * Returns report delay timestamp based on the device clock.
209      */
getReportDelayMillis()210     public long getReportDelayMillis() {
211         return mReportDelayMillis;
212     }
213 
ScanSettings(int scanMode, int callbackType, int scanResultType, long reportDelayMillis, int matchMode, int numOfMatchesPerFilter, boolean legacy, int phy)214     private ScanSettings(int scanMode, int callbackType, int scanResultType,
215             long reportDelayMillis, int matchMode,
216             int numOfMatchesPerFilter, boolean legacy, int phy) {
217         mScanMode = scanMode;
218         mCallbackType = callbackType;
219         mScanResultType = scanResultType;
220         mReportDelayMillis = reportDelayMillis;
221         mNumOfMatchesPerFilter = numOfMatchesPerFilter;
222         mMatchMode = matchMode;
223         mLegacy = legacy;
224         mPhy = phy;
225     }
226 
ScanSettings(Parcel in)227     private ScanSettings(Parcel in) {
228         mScanMode = in.readInt();
229         mCallbackType = in.readInt();
230         mScanResultType = in.readInt();
231         mReportDelayMillis = in.readLong();
232         mMatchMode = in.readInt();
233         mNumOfMatchesPerFilter = in.readInt();
234         mLegacy = in.readInt() != 0;
235         mPhy = in.readInt();
236     }
237 
238     @Override
writeToParcel(Parcel dest, int flags)239     public void writeToParcel(Parcel dest, int flags) {
240         dest.writeInt(mScanMode);
241         dest.writeInt(mCallbackType);
242         dest.writeInt(mScanResultType);
243         dest.writeLong(mReportDelayMillis);
244         dest.writeInt(mMatchMode);
245         dest.writeInt(mNumOfMatchesPerFilter);
246         dest.writeInt(mLegacy ? 1 : 0);
247         dest.writeInt(mPhy);
248     }
249 
250     @Override
describeContents()251     public int describeContents() {
252         return 0;
253     }
254 
255     public static final @android.annotation.NonNull Parcelable.Creator<ScanSettings> CREATOR =
256             new Creator<ScanSettings>() {
257         @Override
258         public ScanSettings[] newArray(int size) {
259             return new ScanSettings[size];
260         }
261 
262         @Override
263         public ScanSettings createFromParcel(Parcel in) {
264             return new ScanSettings(in);
265         }
266     };
267 
268     /**
269      * Builder for {@link ScanSettings}.
270      */
271     public static final class Builder {
272         private int mScanMode = SCAN_MODE_LOW_POWER;
273         private int mCallbackType = CALLBACK_TYPE_ALL_MATCHES;
274         private int mScanResultType = SCAN_RESULT_TYPE_FULL;
275         private long mReportDelayMillis = 0;
276         private int mMatchMode = MATCH_MODE_AGGRESSIVE;
277         private int mNumOfMatchesPerFilter = MATCH_NUM_MAX_ADVERTISEMENT;
278         private boolean mLegacy = true;
279         private int mPhy = PHY_LE_ALL_SUPPORTED;
280 
281         /**
282          * Set scan mode for Bluetooth LE scan.
283          *
284          * @param scanMode The scan mode can be one of {@link ScanSettings#SCAN_MODE_LOW_POWER},
285          * {@link ScanSettings#SCAN_MODE_BALANCED} or {@link ScanSettings#SCAN_MODE_LOW_LATENCY}.
286          * @throws IllegalArgumentException If the {@code scanMode} is invalid.
287          */
setScanMode(int scanMode)288         public Builder setScanMode(int scanMode) {
289             switch (scanMode) {
290                 case SCAN_MODE_OPPORTUNISTIC:
291                 case SCAN_MODE_LOW_POWER:
292                 case SCAN_MODE_BALANCED:
293                 case SCAN_MODE_LOW_LATENCY:
294                 case SCAN_MODE_AMBIENT_DISCOVERY:
295                     mScanMode = scanMode;
296                     break;
297                 default:
298                     throw new IllegalArgumentException("invalid scan mode " + scanMode);
299             }
300             return this;
301         }
302 
303         /**
304          * Set callback type for Bluetooth LE scan.
305          *
306          * @param callbackType The callback type flags for the scan.
307          * @throws IllegalArgumentException If the {@code callbackType} is invalid.
308          */
setCallbackType(int callbackType)309         public Builder setCallbackType(int callbackType) {
310 
311             if (!isValidCallbackType(callbackType)) {
312                 throw new IllegalArgumentException("invalid callback type - " + callbackType);
313             }
314             mCallbackType = callbackType;
315             return this;
316         }
317 
318         // Returns true if the callbackType is valid.
isValidCallbackType(int callbackType)319         private boolean isValidCallbackType(int callbackType) {
320             if (callbackType == CALLBACK_TYPE_ALL_MATCHES
321                     || callbackType == CALLBACK_TYPE_FIRST_MATCH
322                     || callbackType == CALLBACK_TYPE_MATCH_LOST) {
323                 return true;
324             }
325             return callbackType == (CALLBACK_TYPE_FIRST_MATCH | CALLBACK_TYPE_MATCH_LOST);
326         }
327 
328         /**
329          * Set scan result type for Bluetooth LE scan.
330          *
331          * @param scanResultType Type for scan result, could be either {@link
332          * ScanSettings#SCAN_RESULT_TYPE_FULL} or {@link ScanSettings#SCAN_RESULT_TYPE_ABBREVIATED}.
333          * @throws IllegalArgumentException If the {@code scanResultType} is invalid.
334          * @hide
335          */
336         @SystemApi
setScanResultType(int scanResultType)337         public Builder setScanResultType(int scanResultType) {
338             if (scanResultType < SCAN_RESULT_TYPE_FULL
339                     || scanResultType > SCAN_RESULT_TYPE_ABBREVIATED) {
340                 throw new IllegalArgumentException(
341                         "invalid scanResultType - " + scanResultType);
342             }
343             mScanResultType = scanResultType;
344             return this;
345         }
346 
347         /**
348          * Set report delay timestamp for Bluetooth LE scan. If set to 0, you will be notified of
349          * scan results immediately. If &gt; 0, scan results are queued up and delivered after the
350          * requested delay or 5000 milliseconds (whichever is higher). Note scan results may be
351          * delivered sooner if the internal buffers fill up.
352          *
353          * @param reportDelayMillis         how frequently scan results should be delivered in
354          *                                  milliseconds
355          * @throws IllegalArgumentException if {@code reportDelayMillis} &lt; 0
356          */
setReportDelay(long reportDelayMillis)357         public Builder setReportDelay(long reportDelayMillis) {
358             if (reportDelayMillis < 0) {
359                 throw new IllegalArgumentException("reportDelay must be > 0");
360             }
361             mReportDelayMillis = reportDelayMillis;
362             return this;
363         }
364 
365         /**
366          * Set the number of matches for Bluetooth LE scan filters hardware match
367          *
368          * @param numOfMatches The num of matches can be one of
369          * {@link ScanSettings#MATCH_NUM_ONE_ADVERTISEMENT}
370          * or {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or {@link
371          * ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT}
372          * @throws IllegalArgumentException If the {@code matchMode} is invalid.
373          */
setNumOfMatches(int numOfMatches)374         public Builder setNumOfMatches(int numOfMatches) {
375             if (numOfMatches < MATCH_NUM_ONE_ADVERTISEMENT
376                     || numOfMatches > MATCH_NUM_MAX_ADVERTISEMENT) {
377                 throw new IllegalArgumentException("invalid numOfMatches " + numOfMatches);
378             }
379             mNumOfMatchesPerFilter = numOfMatches;
380             return this;
381         }
382 
383         /**
384          * Set match mode for Bluetooth LE scan filters hardware match
385          *
386          * @param matchMode The match mode can be one of {@link ScanSettings#MATCH_MODE_AGGRESSIVE}
387          * or {@link ScanSettings#MATCH_MODE_STICKY}
388          * @throws IllegalArgumentException If the {@code matchMode} is invalid.
389          */
setMatchMode(int matchMode)390         public Builder setMatchMode(int matchMode) {
391             if (matchMode < MATCH_MODE_AGGRESSIVE
392                     || matchMode > MATCH_MODE_STICKY) {
393                 throw new IllegalArgumentException("invalid matchMode " + matchMode);
394             }
395             mMatchMode = matchMode;
396             return this;
397         }
398 
399         /**
400          * Set whether only legacy advertisments should be returned in scan results.
401          * Legacy advertisements include advertisements as specified by the
402          * Bluetooth core specification 4.2 and below. This is true by default
403          * for compatibility with older apps.
404          *
405          * @param legacy true if only legacy advertisements will be returned
406          */
setLegacy(boolean legacy)407         public Builder setLegacy(boolean legacy) {
408             mLegacy = legacy;
409             return this;
410         }
411 
412         /**
413          * Set the Physical Layer to use during this scan.
414          * This is used only if {@link ScanSettings.Builder#setLegacy}
415          * is set to false.
416          * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}
417          * may be used to check whether LE Coded phy is supported by calling
418          * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}.
419          * Selecting an unsupported phy will result in failure to start scan.
420          *
421          * @param phy Can be one of {@link BluetoothDevice#PHY_LE_1M}, {@link
422          * BluetoothDevice#PHY_LE_CODED} or {@link ScanSettings#PHY_LE_ALL_SUPPORTED}
423          */
setPhy(int phy)424         public Builder setPhy(int phy) {
425             mPhy = phy;
426             return this;
427         }
428 
429         /**
430          * Build {@link ScanSettings}.
431          */
build()432         public ScanSettings build() {
433             return new ScanSettings(mScanMode, mCallbackType, mScanResultType,
434                     mReportDelayMillis, mMatchMode,
435                     mNumOfMatchesPerFilter, mLegacy, mPhy);
436         }
437     }
438 }
439