Home | History | Annotate | Download | only in le
      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.os.Parcel;
     21 import 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  */
     27 public 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      */
     63     public static final int CALLBACK_TYPE_FIRST_MATCH = 2;
     64 
     65     /**
     66      * Receive a callback when advertisements are no longer received from a device that has been
     67      * previously reported by a first match callback.
     68      */
     69     public static final int CALLBACK_TYPE_MATCH_LOST = 4;
     70 
     71 
     72     /**
     73      * Determines how many advertisements to match per filter, as this is scarce hw resource
     74      */
     75     /**
     76      * Match one advertisement per filter
     77      */
     78     public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1;
     79 
     80     /**
     81      * Match few advertisement per filter, depends on current capability and availibility of
     82      * the resources in hw
     83      */
     84     public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2;
     85 
     86     /**
     87      * Match as many advertisement per filter as hw could allow, depends on current
     88      * capability and availibility of the resources in hw
     89      */
     90     public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3;
     91 
     92 
     93     /**
     94      * In Aggressive mode, hw will determine a match sooner even with feeble signal strength
     95      * and few number of sightings/match in a duration.
     96      */
     97     public static final int MATCH_MODE_AGGRESSIVE = 1;
     98 
     99     /**
    100      * For sticky mode, higher threshold of signal strength and sightings is required
    101      * before reporting by hw
    102      */
    103     public static final int MATCH_MODE_STICKY = 2;
    104 
    105     /**
    106      * Request full scan results which contain the device, rssi, advertising data, scan response
    107      * as well as the scan timestamp.
    108      *
    109      * @hide
    110      */
    111     @SystemApi
    112     public static final int SCAN_RESULT_TYPE_FULL = 0;
    113 
    114     /**
    115      * Request abbreviated scan results which contain the device, rssi and scan timestamp.
    116      * <p>
    117      * <b>Note:</b> It is possible for an application to get more scan results than it asked for, if
    118      * there are multiple apps using this type.
    119      *
    120      * @hide
    121      */
    122     @SystemApi
    123     public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1;
    124 
    125     // Bluetooth LE scan mode.
    126     private int mScanMode;
    127 
    128     // Bluetooth LE scan callback type
    129     private int mCallbackType;
    130 
    131     // Bluetooth LE scan result type
    132     private int mScanResultType;
    133 
    134     // Time of delay for reporting the scan result
    135     private long mReportDelayMillis;
    136 
    137     private int mMatchMode;
    138 
    139     private int mNumOfMatchesPerFilter;
    140 
    141     public int getScanMode() {
    142         return mScanMode;
    143     }
    144 
    145     public int getCallbackType() {
    146         return mCallbackType;
    147     }
    148 
    149     public int getScanResultType() {
    150         return mScanResultType;
    151     }
    152 
    153     /**
    154      * @hide
    155      */
    156     public int getMatchMode() {
    157         return mMatchMode;
    158     }
    159 
    160     /**
    161      * @hide
    162      */
    163     public int getNumOfMatches() {
    164         return mNumOfMatchesPerFilter;
    165     }
    166 
    167     /**
    168      * Returns report delay timestamp based on the device clock.
    169      */
    170     public long getReportDelayMillis() {
    171         return mReportDelayMillis;
    172     }
    173 
    174     private ScanSettings(int scanMode, int callbackType, int scanResultType,
    175             long reportDelayMillis, int matchMode, int numOfMatchesPerFilter) {
    176         mScanMode = scanMode;
    177         mCallbackType = callbackType;
    178         mScanResultType = scanResultType;
    179         mReportDelayMillis = reportDelayMillis;
    180         mNumOfMatchesPerFilter = numOfMatchesPerFilter;
    181         mMatchMode = matchMode;
    182     }
    183 
    184     private ScanSettings(Parcel in) {
    185         mScanMode = in.readInt();
    186         mCallbackType = in.readInt();
    187         mScanResultType = in.readInt();
    188         mReportDelayMillis = in.readLong();
    189         mMatchMode = in.readInt();
    190         mNumOfMatchesPerFilter = in.readInt();
    191     }
    192 
    193     @Override
    194     public void writeToParcel(Parcel dest, int flags) {
    195         dest.writeInt(mScanMode);
    196         dest.writeInt(mCallbackType);
    197         dest.writeInt(mScanResultType);
    198         dest.writeLong(mReportDelayMillis);
    199         dest.writeInt(mMatchMode);
    200         dest.writeInt(mNumOfMatchesPerFilter);
    201     }
    202 
    203     @Override
    204     public int describeContents() {
    205         return 0;
    206     }
    207 
    208     public static final Parcelable.Creator<ScanSettings>
    209             CREATOR = new Creator<ScanSettings>() {
    210                     @Override
    211                 public ScanSettings[] newArray(int size) {
    212                     return new ScanSettings[size];
    213                 }
    214 
    215                     @Override
    216                 public ScanSettings createFromParcel(Parcel in) {
    217                     return new ScanSettings(in);
    218                 }
    219             };
    220 
    221     /**
    222      * Builder for {@link ScanSettings}.
    223      */
    224     public static final class Builder {
    225         private int mScanMode = SCAN_MODE_LOW_POWER;
    226         private int mCallbackType = CALLBACK_TYPE_ALL_MATCHES;
    227         private int mScanResultType = SCAN_RESULT_TYPE_FULL;
    228         private long mReportDelayMillis = 0;
    229         private int mMatchMode = MATCH_MODE_AGGRESSIVE;
    230         private int mNumOfMatchesPerFilter  = MATCH_NUM_MAX_ADVERTISEMENT;
    231         /**
    232          * Set scan mode for Bluetooth LE scan.
    233          *
    234          * @param scanMode The scan mode can be one of {@link ScanSettings#SCAN_MODE_LOW_POWER},
    235          *            {@link ScanSettings#SCAN_MODE_BALANCED} or
    236          *            {@link ScanSettings#SCAN_MODE_LOW_LATENCY}.
    237          * @throws IllegalArgumentException If the {@code scanMode} is invalid.
    238          */
    239         public Builder setScanMode(int scanMode) {
    240             if (scanMode < SCAN_MODE_OPPORTUNISTIC || scanMode > SCAN_MODE_LOW_LATENCY) {
    241                 throw new IllegalArgumentException("invalid scan mode " + scanMode);
    242             }
    243             mScanMode = scanMode;
    244             return this;
    245         }
    246 
    247         /**
    248          * Set callback type for Bluetooth LE scan.
    249          *
    250          * @param callbackType The callback type flags for the scan.
    251          * @throws IllegalArgumentException If the {@code callbackType} is invalid.
    252          */
    253         public Builder setCallbackType(int callbackType) {
    254 
    255             if (!isValidCallbackType(callbackType)) {
    256                 throw new IllegalArgumentException("invalid callback type - " + callbackType);
    257             }
    258             mCallbackType = callbackType;
    259             return this;
    260         }
    261 
    262         // Returns true if the callbackType is valid.
    263         private boolean isValidCallbackType(int callbackType) {
    264             if (callbackType == CALLBACK_TYPE_ALL_MATCHES ||
    265                     callbackType == CALLBACK_TYPE_FIRST_MATCH ||
    266                     callbackType == CALLBACK_TYPE_MATCH_LOST) {
    267                 return true;
    268             }
    269             return callbackType == (CALLBACK_TYPE_FIRST_MATCH | CALLBACK_TYPE_MATCH_LOST);
    270         }
    271 
    272         /**
    273          * Set scan result type for Bluetooth LE scan.
    274          *
    275          * @param scanResultType Type for scan result, could be either
    276          *            {@link ScanSettings#SCAN_RESULT_TYPE_FULL} or
    277          *            {@link ScanSettings#SCAN_RESULT_TYPE_ABBREVIATED}.
    278          * @throws IllegalArgumentException If the {@code scanResultType} is invalid.
    279          * @hide
    280          */
    281         @SystemApi
    282         public Builder setScanResultType(int scanResultType) {
    283             if (scanResultType < SCAN_RESULT_TYPE_FULL
    284                     || scanResultType > SCAN_RESULT_TYPE_ABBREVIATED) {
    285                 throw new IllegalArgumentException(
    286                         "invalid scanResultType - " + scanResultType);
    287             }
    288             mScanResultType = scanResultType;
    289             return this;
    290         }
    291 
    292         /**
    293          * Set report delay timestamp for Bluetooth LE scan.
    294          *
    295          * @param reportDelayMillis Delay of report in milliseconds. Set to 0 to be notified of
    296          *            results immediately. Values &gt; 0 causes the scan results to be queued up and
    297          *            delivered after the requested delay or when the internal buffers fill up.
    298          * @throws IllegalArgumentException If {@code reportDelayMillis} &lt; 0.
    299          */
    300         public Builder setReportDelay(long reportDelayMillis) {
    301             if (reportDelayMillis < 0) {
    302                 throw new IllegalArgumentException("reportDelay must be > 0");
    303             }
    304             mReportDelayMillis = reportDelayMillis;
    305             return this;
    306         }
    307 
    308         /**
    309          * Set the number of matches for Bluetooth LE scan filters hardware match
    310          *
    311          * @param numOfMatches The num of matches can be one of
    312          *              {@link ScanSettings#MATCH_NUM_ONE_ADVERTISEMENT} or
    313          *              {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or
    314          *              {@link ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT}
    315          * @throws IllegalArgumentException If the {@code matchMode} is invalid.
    316          */
    317         public Builder setNumOfMatches(int numOfMatches) {
    318             if (numOfMatches < MATCH_NUM_ONE_ADVERTISEMENT
    319                     || numOfMatches > MATCH_NUM_MAX_ADVERTISEMENT) {
    320                 throw new IllegalArgumentException("invalid numOfMatches " + numOfMatches);
    321             }
    322             mNumOfMatchesPerFilter = numOfMatches;
    323             return this;
    324         }
    325 
    326         /**
    327          * Set match mode for Bluetooth LE scan filters hardware match
    328          *
    329          * @param matchMode The match mode can be one of
    330          *              {@link ScanSettings#MATCH_MODE_AGGRESSIVE} or
    331          *              {@link ScanSettings#MATCH_MODE_STICKY}
    332          * @throws IllegalArgumentException If the {@code matchMode} is invalid.
    333          */
    334         public Builder setMatchMode(int matchMode) {
    335             if (matchMode < MATCH_MODE_AGGRESSIVE
    336                     || matchMode > MATCH_MODE_STICKY) {
    337                 throw new IllegalArgumentException("invalid matchMode " + matchMode);
    338             }
    339             mMatchMode = matchMode;
    340             return this;
    341         }
    342 
    343         /**
    344          * Build {@link ScanSettings}.
    345          */
    346         public ScanSettings build() {
    347             return new ScanSettings(mScanMode, mCallbackType, mScanResultType,
    348                     mReportDelayMillis, mMatchMode, mNumOfMatchesPerFilter);
    349         }
    350     }
    351 }
    352