ScanSettings.java revision e593d0aec6430d98731d9751facd0414a1c9c6a2
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
17package android.bluetooth.le;
18
19import android.annotation.SystemApi;
20import android.os.Parcel;
21import android.os.Parcelable;
22
23/**
24 * Bluetooth LE scan settings are passed to {@link BluetoothLeScanner#startScan} to define the
25 * parameters for the scan.
26 */
27public final class ScanSettings implements Parcelable {
28
29    /**
30     * A special Bluetooth LE scan mode. Applications using this scan mode will passively listen for
31     * other scan results without starting BLE scans themselves.
32     */
33    public static final int SCAN_MODE_OPPORTUNISTIC = -1;
34
35    /**
36     * Perform Bluetooth LE scan in low power mode. This is the default scan mode as it consumes the
37     * least power.
38     */
39    public static final int SCAN_MODE_LOW_POWER = 0;
40
41    /**
42     * Perform Bluetooth LE scan in balanced power mode. Scan results are returned at a rate that
43     * provides a good trade-off between scan frequency and power consumption.
44     */
45    public static final int SCAN_MODE_BALANCED = 1;
46
47    /**
48     * Scan using highest duty cycle. It's recommended to only use this mode when the application is
49     * running in the foreground.
50     */
51    public static final int SCAN_MODE_LOW_LATENCY = 2;
52
53    /**
54     * Trigger a callback for every Bluetooth advertisement found that matches the filter criteria.
55     * If no filter is active, all advertisement packets are reported.
56     */
57    public static final int CALLBACK_TYPE_ALL_MATCHES = 1;
58
59    /**
60     * A result callback is only triggered for the first advertisement packet received that matches
61     * the filter criteria.
62     * @hide
63     */
64    @SystemApi
65    public static final int CALLBACK_TYPE_FIRST_MATCH = 2;
66
67    /**
68     * Receive a callback when advertisements are no longer received from a device that has been
69     * previously reported by a first match callback.
70     * @hide
71     */
72    @SystemApi
73    public static final int CALLBACK_TYPE_MATCH_LOST = 4;
74
75
76    /**
77     * Determines how many advertisements to match per filter, as this is scarce hw resource
78     */
79    /**
80     * Match one advertisement per filter
81     * @hide
82     */
83    public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1;
84
85    /**
86     * Match few advertisement per filter, depends on current capability and availibility of
87     * the resources in hw
88     * @hide
89     */
90    public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2;
91
92    /**
93     * Match as many advertisement per filter as hw could allow, depends on current
94     * capability and availibility of the resources in hw
95     * @hide
96     */
97    public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3;
98
99
100    /**
101     * In Aggressive mode, hw will determine a match sooner even with feeble signal strength
102     * and few number of sightings/match in a duration.
103     * @hide
104     */
105    public static final int MATCH_MODE_AGGRESSIVE = 1;
106
107    /**
108     * For sticky mode, higher threshold of signal strength and sightings is required
109     * before reporting by hw
110     * @hide
111     */
112    public static final int MATCH_MODE_STICKY = 2;
113
114    /**
115     * Request full scan results which contain the device, rssi, advertising data, scan response
116     * as well as the scan timestamp.
117     *
118     * @hide
119     */
120    @SystemApi
121    public static final int SCAN_RESULT_TYPE_FULL = 0;
122
123    /**
124     * Request abbreviated scan results which contain the device, rssi and scan timestamp.
125     * <p>
126     * <b>Note:</b> It is possible for an application to get more scan results than it asked for, if
127     * there are multiple apps using this type.
128     *
129     * @hide
130     */
131    @SystemApi
132    public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1;
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    public int getScanMode() {
151        return mScanMode;
152    }
153
154    public int getCallbackType() {
155        return mCallbackType;
156    }
157
158    public int getScanResultType() {
159        return mScanResultType;
160    }
161
162    /**
163     * @hide
164     */
165    public int getMatchMode() {
166        return mMatchMode;
167    }
168
169    /**
170     * @hide
171     */
172    public int getNumOfMatches() {
173        return mNumOfMatchesPerFilter;
174    }
175
176    /**
177     * Returns report delay timestamp based on the device clock.
178     */
179    public long getReportDelayMillis() {
180        return mReportDelayMillis;
181    }
182
183    private ScanSettings(int scanMode, int callbackType, int scanResultType,
184            long reportDelayMillis, int matchMode, int numOfMatchesPerFilter) {
185        mScanMode = scanMode;
186        mCallbackType = callbackType;
187        mScanResultType = scanResultType;
188        mReportDelayMillis = reportDelayMillis;
189        mNumOfMatchesPerFilter = numOfMatchesPerFilter;
190        mMatchMode = numOfMatchesPerFilter;
191    }
192
193    private ScanSettings(Parcel in) {
194        mScanMode = in.readInt();
195        mCallbackType = in.readInt();
196        mScanResultType = in.readInt();
197        mReportDelayMillis = in.readLong();
198        mMatchMode = in.readInt();
199        mNumOfMatchesPerFilter = in.readInt();
200    }
201
202    @Override
203    public void writeToParcel(Parcel dest, int flags) {
204        dest.writeInt(mScanMode);
205        dest.writeInt(mCallbackType);
206        dest.writeInt(mScanResultType);
207        dest.writeLong(mReportDelayMillis);
208        dest.writeInt(mMatchMode);
209        dest.writeInt(mNumOfMatchesPerFilter);
210    }
211
212    @Override
213    public int describeContents() {
214        return 0;
215    }
216
217    public static final Parcelable.Creator<ScanSettings>
218            CREATOR = new Creator<ScanSettings>() {
219                    @Override
220                public ScanSettings[] newArray(int size) {
221                    return new ScanSettings[size];
222                }
223
224                    @Override
225                public ScanSettings createFromParcel(Parcel in) {
226                    return new ScanSettings(in);
227                }
228            };
229
230    /**
231     * Builder for {@link ScanSettings}.
232     */
233    public static final class Builder {
234        private int mScanMode = SCAN_MODE_LOW_POWER;
235        private int mCallbackType = CALLBACK_TYPE_ALL_MATCHES;
236        private int mScanResultType = SCAN_RESULT_TYPE_FULL;
237        private long mReportDelayMillis = 0;
238        private int mMatchMode = MATCH_MODE_AGGRESSIVE;
239        private int mNumOfMatchesPerFilter  = MATCH_NUM_ONE_ADVERTISEMENT;
240        /**
241         * Set scan mode for Bluetooth LE scan.
242         *
243         * @param scanMode The scan mode can be one of {@link ScanSettings#SCAN_MODE_LOW_POWER},
244         *            {@link ScanSettings#SCAN_MODE_BALANCED} or
245         *            {@link ScanSettings#SCAN_MODE_LOW_LATENCY}.
246         * @throws IllegalArgumentException If the {@code scanMode} is invalid.
247         */
248        public Builder setScanMode(int scanMode) {
249            if (scanMode < SCAN_MODE_OPPORTUNISTIC || scanMode > SCAN_MODE_LOW_LATENCY) {
250                throw new IllegalArgumentException("invalid scan mode " + scanMode);
251            }
252            mScanMode = scanMode;
253            return this;
254        }
255
256        /**
257         * Set callback type for Bluetooth LE scan.
258         *
259         * @param callbackType The callback type flags for the scan.
260         * @throws IllegalArgumentException If the {@code callbackType} is invalid.
261         * @hide
262         */
263        @SystemApi
264        public Builder setCallbackType(int callbackType) {
265
266            if (!isValidCallbackType(callbackType)) {
267                throw new IllegalArgumentException("invalid callback type - " + callbackType);
268            }
269            mCallbackType = callbackType;
270            return this;
271        }
272
273        // Returns true if the callbackType is valid.
274        private boolean isValidCallbackType(int callbackType) {
275            if (callbackType == CALLBACK_TYPE_ALL_MATCHES ||
276                    callbackType == CALLBACK_TYPE_FIRST_MATCH ||
277                    callbackType == CALLBACK_TYPE_MATCH_LOST) {
278                return true;
279            }
280            return callbackType == (CALLBACK_TYPE_FIRST_MATCH | CALLBACK_TYPE_MATCH_LOST);
281        }
282
283        /**
284         * Set scan result type for Bluetooth LE scan.
285         *
286         * @param scanResultType Type for scan result, could be either
287         *            {@link ScanSettings#SCAN_RESULT_TYPE_FULL} or
288         *            {@link ScanSettings#SCAN_RESULT_TYPE_ABBREVIATED}.
289         * @throws IllegalArgumentException If the {@code scanResultType} is invalid.
290         * @hide
291         */
292        @SystemApi
293        public Builder setScanResultType(int scanResultType) {
294            if (scanResultType < SCAN_RESULT_TYPE_FULL
295                    || scanResultType > SCAN_RESULT_TYPE_ABBREVIATED) {
296                throw new IllegalArgumentException(
297                        "invalid scanResultType - " + scanResultType);
298            }
299            mScanResultType = scanResultType;
300            return this;
301        }
302
303        /**
304         * Set report delay timestamp for Bluetooth LE scan.
305         *
306         * @param reportDelayMillis Delay of report in milliseconds. Set to 0 to be notified of
307         *            results immediately. Values &gt; 0 causes the scan results to be queued up and
308         *            delivered after the requested delay or when the internal buffers fill up.
309         * @throws IllegalArgumentException If {@code reportDelayMillis} &lt; 0.
310         */
311        public Builder setReportDelay(long reportDelayMillis) {
312            if (reportDelayMillis < 0) {
313                throw new IllegalArgumentException("reportDelay must be > 0");
314            }
315            mReportDelayMillis = reportDelayMillis;
316            return this;
317        }
318
319        /**
320         * Set the number of matches for Bluetooth LE scan filters hardware match
321         *
322         * @param numOfMatches The num of matches can be one of
323         *              {@link ScanSettings#MATCH_NUM_ONE_ADVERTISEMENT} or
324         *              {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or
325         *              {@link ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT}
326         * @throws IllegalArgumentException If the {@code matchMode} is invalid.
327         * @hide
328         */
329        public Builder setNumOfMatches(int numOfMatches) {
330            if (numOfMatches < MATCH_NUM_ONE_ADVERTISEMENT
331                    || numOfMatches > MATCH_NUM_MAX_ADVERTISEMENT) {
332                throw new IllegalArgumentException("invalid numOfMatches " + numOfMatches);
333            }
334            mNumOfMatchesPerFilter = numOfMatches;
335            return this;
336        }
337
338        /**
339         * Set match mode for Bluetooth LE scan filters hardware match
340         *
341         * @param matchMode The match mode can be one of
342         *              {@link ScanSettings#MATCH_MODE_AGGRESSIVE} or
343         *              {@link ScanSettings#MATCH_MODE_STICKY}
344         * @throws IllegalArgumentException If the {@code matchMode} is invalid.
345         * @hide
346         */
347        public Builder setMatchMode(int matchMode) {
348            if (matchMode < MATCH_MODE_AGGRESSIVE
349                    || matchMode > MATCH_MODE_STICKY) {
350                throw new IllegalArgumentException("invalid matchMode " + matchMode);
351            }
352            mMatchMode = matchMode;
353            return this;
354        }
355
356        /**
357         * Build {@link ScanSettings}.
358         */
359        public ScanSettings build() {
360            return new ScanSettings(mScanMode, mCallbackType, mScanResultType,
361                    mReportDelayMillis, mMatchMode, mNumOfMatchesPerFilter);
362        }
363    }
364}
365