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