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