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 > 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} < 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