From 3aca933861822f66984a9a3ae1db8242fe6c9521 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Tue, 17 Jan 2017 07:50:46 -0800 Subject: [PATCH] Bluetooth 5 enhanced scanning API Bug: 30622771 Test: manual Change-Id: I2c8065fbcedf48777ce18c7d8fe621e568b3fd75 (cherry picked from commit 9de522c6e48497028d36a1f8ad8f8adf4b7b1ae6) --- api/current.txt | 25 ++- api/system-current.txt | 25 ++- api/test-current.txt | 25 ++- .../java/android/bluetooth/le/ScanResult.java | 205 +++++++++++++++++- .../android/bluetooth/le/ScanSettings.java | 86 +++++++- 5 files changed, 350 insertions(+), 16 deletions(-) diff --git a/api/current.txt b/api/current.txt index ac91a0a7281d1..3e99316ed6553 100644 --- a/api/current.txt +++ b/api/current.txt @@ -7544,19 +7544,37 @@ package android.bluetooth.le { } public final class ScanResult implements android.os.Parcelable { - ctor public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long); + ctor public deprecated ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long); + ctor public ScanResult(android.bluetooth.BluetoothDevice, int, int, int, int, int, int, int, android.bluetooth.le.ScanRecord, long); method public int describeContents(); + method public int getAdvertisingSid(); + method public int getDataStatus(); method public android.bluetooth.BluetoothDevice getDevice(); + method public int getPeriodicAdvertisingInterval(); + method public int getPrimaryPhy(); method public int getRssi(); method public android.bluetooth.le.ScanRecord getScanRecord(); + method public int getSecondaryPhy(); method public long getTimestampNanos(); + method public int getTxPower(); + method public boolean isConnectable(); + method public boolean isLegacy(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; + field public static final int DATA_COMPLETE = 0; // 0x0 + field public static final int DATA_TRUNCATED = 2; // 0x2 + field public static final int PHY_LE_1M = 1; // 0x1 + field public static final int PHY_LE_2M = 2; // 0x2 + field public static final int PHY_LE_CODED = 3; // 0x3 + field public static final int PHY_UNUSED = 0; // 0x0 + field public static final int SID_NOT_PRESENT = 255; // 0xff } public final class ScanSettings implements android.os.Parcelable { method public int describeContents(); method public int getCallbackType(); + method public boolean getLegacy(); + method public int getPhy(); method public long getReportDelayMillis(); method public int getScanMode(); method public int getScanResultType(); @@ -7570,6 +7588,9 @@ package android.bluetooth.le { field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2 field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3 field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1 + field public static final int PHY_LE_1M = 1; // 0x1 + field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff + field public static final int PHY_LE_CODED = 3; // 0x3 field public static final int SCAN_MODE_BALANCED = 1; // 0x1 field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2 field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0 @@ -7580,8 +7601,10 @@ package android.bluetooth.le { ctor public ScanSettings.Builder(); method public android.bluetooth.le.ScanSettings build(); method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int); + method public android.bluetooth.le.ScanSettings.Builder setLegacy(boolean); method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int); method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int); + method public android.bluetooth.le.ScanSettings.Builder setPhy(int); method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long); method public android.bluetooth.le.ScanSettings.Builder setScanMode(int); } diff --git a/api/system-current.txt b/api/system-current.txt index c122fcccddb9a..078a988eb4c54 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -7861,19 +7861,37 @@ package android.bluetooth.le { } public final class ScanResult implements android.os.Parcelable { - ctor public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long); + ctor public deprecated ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long); + ctor public ScanResult(android.bluetooth.BluetoothDevice, int, int, int, int, int, int, int, android.bluetooth.le.ScanRecord, long); method public int describeContents(); + method public int getAdvertisingSid(); + method public int getDataStatus(); method public android.bluetooth.BluetoothDevice getDevice(); + method public int getPeriodicAdvertisingInterval(); + method public int getPrimaryPhy(); method public int getRssi(); method public android.bluetooth.le.ScanRecord getScanRecord(); + method public int getSecondaryPhy(); method public long getTimestampNanos(); + method public int getTxPower(); + method public boolean isConnectable(); + method public boolean isLegacy(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; + field public static final int DATA_COMPLETE = 0; // 0x0 + field public static final int DATA_TRUNCATED = 2; // 0x2 + field public static final int PHY_LE_1M = 1; // 0x1 + field public static final int PHY_LE_2M = 2; // 0x2 + field public static final int PHY_LE_CODED = 3; // 0x3 + field public static final int PHY_UNUSED = 0; // 0x0 + field public static final int SID_NOT_PRESENT = 255; // 0xff } public final class ScanSettings implements android.os.Parcelable { method public int describeContents(); method public int getCallbackType(); + method public boolean getLegacy(); + method public int getPhy(); method public long getReportDelayMillis(); method public int getScanMode(); method public int getScanResultType(); @@ -7887,6 +7905,9 @@ package android.bluetooth.le { field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2 field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3 field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1 + field public static final int PHY_LE_1M = 1; // 0x1 + field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff + field public static final int PHY_LE_CODED = 3; // 0x3 field public static final int SCAN_MODE_BALANCED = 1; // 0x1 field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2 field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0 @@ -7899,8 +7920,10 @@ package android.bluetooth.le { ctor public ScanSettings.Builder(); method public android.bluetooth.le.ScanSettings build(); method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int); + method public android.bluetooth.le.ScanSettings.Builder setLegacy(boolean); method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int); method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int); + method public android.bluetooth.le.ScanSettings.Builder setPhy(int); method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long); method public android.bluetooth.le.ScanSettings.Builder setScanMode(int); method public android.bluetooth.le.ScanSettings.Builder setScanResultType(int); diff --git a/api/test-current.txt b/api/test-current.txt index 03374bd5382a5..b7c9acefab3e6 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -7553,19 +7553,37 @@ package android.bluetooth.le { } public final class ScanResult implements android.os.Parcelable { - ctor public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long); + ctor public deprecated ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long); + ctor public ScanResult(android.bluetooth.BluetoothDevice, int, int, int, int, int, int, int, android.bluetooth.le.ScanRecord, long); method public int describeContents(); + method public int getAdvertisingSid(); + method public int getDataStatus(); method public android.bluetooth.BluetoothDevice getDevice(); + method public int getPeriodicAdvertisingInterval(); + method public int getPrimaryPhy(); method public int getRssi(); method public android.bluetooth.le.ScanRecord getScanRecord(); + method public int getSecondaryPhy(); method public long getTimestampNanos(); + method public int getTxPower(); + method public boolean isConnectable(); + method public boolean isLegacy(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; + field public static final int DATA_COMPLETE = 0; // 0x0 + field public static final int DATA_TRUNCATED = 2; // 0x2 + field public static final int PHY_LE_1M = 1; // 0x1 + field public static final int PHY_LE_2M = 2; // 0x2 + field public static final int PHY_LE_CODED = 3; // 0x3 + field public static final int PHY_UNUSED = 0; // 0x0 + field public static final int SID_NOT_PRESENT = 255; // 0xff } public final class ScanSettings implements android.os.Parcelable { method public int describeContents(); method public int getCallbackType(); + method public boolean getLegacy(); + method public int getPhy(); method public long getReportDelayMillis(); method public int getScanMode(); method public int getScanResultType(); @@ -7579,6 +7597,9 @@ package android.bluetooth.le { field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2 field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3 field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1 + field public static final int PHY_LE_1M = 1; // 0x1 + field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff + field public static final int PHY_LE_CODED = 3; // 0x3 field public static final int SCAN_MODE_BALANCED = 1; // 0x1 field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2 field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0 @@ -7589,8 +7610,10 @@ package android.bluetooth.le { ctor public ScanSettings.Builder(); method public android.bluetooth.le.ScanSettings build(); method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int); + method public android.bluetooth.le.ScanSettings.Builder setLegacy(boolean); method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int); method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int); + method public android.bluetooth.le.ScanSettings.Builder setPhy(int); method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long); method public android.bluetooth.le.ScanSettings.Builder setScanMode(int); } diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java index 2fdfe7f8a83fb..f92357b59c7d5 100644 --- a/core/java/android/bluetooth/le/ScanResult.java +++ b/core/java/android/bluetooth/le/ScanResult.java @@ -27,7 +27,56 @@ import java.util.Objects; * ScanResult for Bluetooth LE scan. */ public final class ScanResult implements Parcelable { - // Remote bluetooth device. + + /** + * For chained advertisements, inidcates tha the data contained in this + * scan result is complete. + */ + public static final int DATA_COMPLETE = 0x00; + + /** + * For chained advertisements, indicates that the controller was + * unable to receive all chained packets and the scan result contains + * incomplete truncated data. + */ + public static final int DATA_TRUNCATED = 0x02; + + /** + * Indicates that the secondary physical layer was not used. + */ + public static final int PHY_UNUSED = 0x00; + + /** + * Bluetooth LE 1Mbit advertiser PHY. + */ + public static final int PHY_LE_1M = 0x01; + + /** + * Bluetooth LE 2Mbit advertiser PHY. + */ + public static final int PHY_LE_2M = 0x02; + + /** + * Bluetooth LE Coded advertiser PHY. + */ + public static final int PHY_LE_CODED = 0x03; + + /** + * Advertising Set ID is not present in the packet. + */ + public static final int SID_NOT_PRESENT = 0xFF; + + /** + * Mask for checking wether event type represents legacy advertisement. + */ + private static final int ET_LEGACY_MASK = 0x10; + + /** + * Mask for checking wether event type represents connectable advertisement. + */ + private static final int ET_CONNECTABLE_MASK = 0x01; + + // Remote Bluetooth device. private BluetoothDevice mDevice; // Scan record, including advertising data and scan response data. @@ -40,13 +89,21 @@ public final class ScanResult implements Parcelable { // Device timestamp when the result was last seen. private long mTimestampNanos; + private int mEventType; + private int mPrimaryPhy; + private int mSecondaryPhy; + private int mAdvertisingSid; + private int mTxPower; + private int mPeriodicAdvertisingInterval; + /** - * Constructor of scan result. + * Constructs a new ScanResult. * - * @param device Remote bluetooth device that is found. + * @param device Remote Bluetooth device found. * @param scanRecord Scan record including both advertising data and scan response data. * @param rssi Received signal strength. - * @param timestampNanos Device timestamp when the scan result was observed. + * @param timestampNanos Timestamp at which the scan result was observed. + * @deprecated use {@link #ScanResult(BluetoothDevice, int, int, int, int, int, int, int, ScanRecord, long)} */ public ScanResult(BluetoothDevice device, ScanRecord scanRecord, int rssi, long timestampNanos) { @@ -54,6 +111,41 @@ public final class ScanResult implements Parcelable { mScanRecord = scanRecord; mRssi = rssi; mTimestampNanos = timestampNanos; + mEventType = (DATA_COMPLETE << 5) | ET_LEGACY_MASK | ET_CONNECTABLE_MASK; + mPrimaryPhy = PHY_LE_1M; + mSecondaryPhy = PHY_UNUSED; + mAdvertisingSid = SID_NOT_PRESENT; + mTxPower = 127; + mPeriodicAdvertisingInterval = 0; + } + + /** + * Constructs a new ScanResult. + * + * @param device Remote Bluetooth device found. + * @param eventType Event type. + * @param primaryPhy Primary advertising phy. + * @param secondaryPhy Secondary advertising phy. + * @param advertisingSid Advertising set ID. + * @param txPower Transmit power. + * @param rssi Received signal strength. + * @param periodicAdvertisingInterval Periodic advertising interval. + * @param scanRecord Scan record including both advertising data and scan response data. + * @param timestampNanos Timestamp at which the scan result was observed. + */ + public ScanResult(BluetoothDevice device, int eventType, int primaryPhy, int secondaryPhy, + int advertisingSid, int txPower, int rssi, int periodicAdvertisingInterval, + ScanRecord scanRecord, long timestampNanos) { + mDevice = device; + mEventType = eventType; + mPrimaryPhy = primaryPhy; + mSecondaryPhy = secondaryPhy; + mAdvertisingSid = advertisingSid; + mTxPower = txPower; + mRssi = rssi; + mPeriodicAdvertisingInterval = periodicAdvertisingInterval; + mScanRecord = scanRecord; + mTimestampNanos = timestampNanos; } private ScanResult(Parcel in) { @@ -76,6 +168,12 @@ public final class ScanResult implements Parcelable { } dest.writeInt(mRssi); dest.writeLong(mTimestampNanos); + dest.writeInt(mEventType); + dest.writeInt(mPrimaryPhy); + dest.writeInt(mSecondaryPhy); + dest.writeInt(mAdvertisingSid); + dest.writeInt(mTxPower); + dest.writeInt(mPeriodicAdvertisingInterval); } private void readFromParcel(Parcel in) { @@ -87,6 +185,12 @@ public final class ScanResult implements Parcelable { } mRssi = in.readInt(); mTimestampNanos = in.readLong(); + mEventType = in.readInt(); + mPrimaryPhy = in.readInt(); + mSecondaryPhy = in.readInt(); + mAdvertisingSid = in.readInt(); + mTxPower = in.readInt(); + mPeriodicAdvertisingInterval = in.readInt(); } @Override @@ -95,7 +199,7 @@ public final class ScanResult implements Parcelable { } /** - * Returns the remote bluetooth device identified by the bluetooth device address. + * Returns the remote Bluetooth device identified by the Bluetooth device address. */ public BluetoothDevice getDevice() { return mDevice; @@ -123,9 +227,79 @@ public final class ScanResult implements Parcelable { return mTimestampNanos; } + /** + * Returns true if this object represents legacy scan result. + * Legacy scan results do not contain advanced advertising information + * as specified in the Bluetooth Core Specification v5. + */ + public boolean isLegacy() { + return (mEventType & ET_LEGACY_MASK) != 0; + } + + /** + * Returns true if this object represents connectable scan result. + */ + public boolean isConnectable() { + return (mEventType & ET_CONNECTABLE_MASK) != 0; + } + + /** + * Returns the data status. + * Can be one of {@link ScanResult#DATA_COMPLETE} or + * {@link ScanResult#DATA_TRUNCATED}. + */ + public int getDataStatus() { + // return bit 5 and 6 + return (mEventType >> 5) & 0x03; + } + + /** + * Returns the primary Physical Layer + * on which this advertisment was received. + * Can be one of {@link ScanResult#PHY_LE_1M} or + * {@link ScanResult#PHY_LE_CODED}. + */ + public int getPrimaryPhy() { return mPrimaryPhy; } + + /** + * Returns the secondary Physical Layer + * on which this advertisment was received. + * Can be one of {@link ScanResult#PHY_LE_1M}, + * {@link ScanResult#PHY_LE_2M}, {@link ScanResult#PHY_LE_CODED} + * or {@link ScanResult#PHY_UNUSED} - if the advertisement + * was not received on a secondary physical channel. + */ + public int getSecondaryPhy() { return mSecondaryPhy; } + + /** + * Returns the advertising set id. + * May return {@link ScanResult#SID_NOT_PRESENT} if + * no set id was is present. + */ + public int getAdvertisingSid() { return mAdvertisingSid; } + + /** + * Returns the transmit power in dBm. + * Valid range is [-127, 126]. A value of 127 indicates that the + * advertisement did not indicate TX power. + */ + public int getTxPower() { return mTxPower; } + + /** + * Returns the periodic advertising interval in units of 1.25ms. + * Valid range is 6 (7.5ms) to 65536 (81918.75ms). A value of 0 means + * periodic advertising is not used for this scan result. + */ + public int getPeriodicAdvertisingInterval() { + return mPeriodicAdvertisingInterval; + } + @Override public int hashCode() { - return Objects.hash(mDevice, mRssi, mScanRecord, mTimestampNanos); + return Objects.hash(mDevice, mRssi, mScanRecord, mTimestampNanos, + mEventType, mPrimaryPhy, mSecondaryPhy, + mAdvertisingSid, mTxPower, + mPeriodicAdvertisingInterval); } @Override @@ -138,15 +312,24 @@ public final class ScanResult implements Parcelable { } ScanResult other = (ScanResult) obj; return Objects.equals(mDevice, other.mDevice) && (mRssi == other.mRssi) && - Objects.equals(mScanRecord, other.mScanRecord) - && (mTimestampNanos == other.mTimestampNanos); + Objects.equals(mScanRecord, other.mScanRecord) && + (mTimestampNanos == other.mTimestampNanos) && + mEventType == other.mEventType && + mPrimaryPhy == other.mPrimaryPhy && + mSecondaryPhy == other.mSecondaryPhy && + mAdvertisingSid == other.mAdvertisingSid && + mTxPower == other.mTxPower && + mPeriodicAdvertisingInterval == other.mPeriodicAdvertisingInterval; } @Override public String toString() { - return "ScanResult{" + "mDevice=" + mDevice + ", mScanRecord=" - + Objects.toString(mScanRecord) + ", mRssi=" + mRssi + ", mTimestampNanos=" - + mTimestampNanos + '}'; + return "ScanResult{" + "device=" + mDevice + ", scanRecord=" + + Objects.toString(mScanRecord) + ", rssi=" + mRssi + + ", timestampNanos=" + mTimestampNanos + ", eventType=" + mEventType + + ", primaryPhy=" + mPrimaryPhy + ", secondaryPhy=" + mSecondaryPhy + + ", advertisingSid=" + mAdvertisingSid + ", txPower=" + mTxPower + + ", periodicAdvertisingInterval=" + mPeriodicAdvertisingInterval + '}'; } public static final Parcelable.Creator CREATOR = new Creator() { diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index d61662469b6c3..69c9a8cece3a8 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -122,6 +122,24 @@ public final class ScanSettings implements Parcelable { @SystemApi public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; + /** + * Use the Bluetooth LE 1Mbit PHY for scanning. + */ + public static final int PHY_LE_1M = 1; + + /** + * Use Bluetooth LE Coded PHY for scanning. + */ + public static final int PHY_LE_CODED = 3; + + /** + * Use all supported PHYs for scanning. + * This will check the controller capabilities, and start + * the scan on 1Mbit and LE Coded PHYs if supported, or on + * the 1Mbit PHY only. + */ + public static final int PHY_LE_ALL_SUPPORTED = 255; + // Bluetooth LE scan mode. private int mScanMode; @@ -138,6 +156,11 @@ public final class ScanSettings implements Parcelable { private int mNumOfMatchesPerFilter; + // Include only legacy advertising results + private boolean mLegacy; + + private int mPhy; + public int getScanMode() { return mScanMode; } @@ -164,6 +187,22 @@ public final class ScanSettings implements Parcelable { return mNumOfMatchesPerFilter; } + /** + * Returns whether only legacy advertisements will be returned. + * Legacy advertisements include advertisements as specified + * by the Bluetooth core specification 4.2 and below. + */ + public boolean getLegacy() { + return mLegacy; + } + + /** + * Returns the physical layer used during a scan. + */ + public int getPhy() { + return mPhy; + } + /** * Returns report delay timestamp based on the device clock. */ @@ -172,13 +211,16 @@ public final class ScanSettings implements Parcelable { } private ScanSettings(int scanMode, int callbackType, int scanResultType, - long reportDelayMillis, int matchMode, int numOfMatchesPerFilter) { + long reportDelayMillis, int matchMode, + int numOfMatchesPerFilter, boolean legacy, int phy) { mScanMode = scanMode; mCallbackType = callbackType; mScanResultType = scanResultType; mReportDelayMillis = reportDelayMillis; mNumOfMatchesPerFilter = numOfMatchesPerFilter; mMatchMode = matchMode; + mLegacy = legacy; + mPhy = phy; } private ScanSettings(Parcel in) { @@ -188,6 +230,8 @@ public final class ScanSettings implements Parcelable { mReportDelayMillis = in.readLong(); mMatchMode = in.readInt(); mNumOfMatchesPerFilter = in.readInt(); + mLegacy = in.readInt() != 0 ? true : false; + mPhy = in.readInt(); } @Override @@ -198,6 +242,8 @@ public final class ScanSettings implements Parcelable { dest.writeLong(mReportDelayMillis); dest.writeInt(mMatchMode); dest.writeInt(mNumOfMatchesPerFilter); + dest.writeInt(mLegacy ? 1 : 0); + dest.writeInt(mPhy); } @Override @@ -228,6 +274,9 @@ public final class ScanSettings implements Parcelable { private long mReportDelayMillis = 0; private int mMatchMode = MATCH_MODE_AGGRESSIVE; private int mNumOfMatchesPerFilter = MATCH_NUM_MAX_ADVERTISEMENT; + private boolean mLegacy = true; + private int mPhy = PHY_LE_ALL_SUPPORTED; + /** * Set scan mode for Bluetooth LE scan. * @@ -340,12 +389,45 @@ public final class ScanSettings implements Parcelable { return this; } + /** + * Set whether only legacy advertisments should be returned in scan results. + * Legacy advertisements include advertisements as specified by the + * Bluetooth core specification 4.2 and below. This is true by default + * for compatibility with older apps. + * + * @param legacy true if only legacy advertisements will be returned + */ + public Builder setLegacy(boolean legacy) { + mLegacy = legacy; + return this; + } + + /** + * Set the Physical Layer to use during this scan. + * This is used only if {@link ScanSettings.Builder#setLegacy} + * is set to false. + * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported} + * may be used to check whether LE Coded phy is supported by calling + * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}. + * Selecting an unsupported phy will result in failure to start scan. + * + * @param phy Can be one of + * {@link ScanSettings#PHY_LE_1M}, + * {@link ScanSettings#PHY_LE_CODED} or + * {@link ScanSettings#PHY_LE_ALL_SUPPORTED} + */ + public Builder setPhy(int phy) { + mPhy = phy; + return this; + } + /** * Build {@link ScanSettings}. */ public ScanSettings build() { return new ScanSettings(mScanMode, mCallbackType, mScanResultType, - mReportDelayMillis, mMatchMode, mNumOfMatchesPerFilter); + mReportDelayMillis, mMatchMode, + mNumOfMatchesPerFilter, mLegacy, mPhy); } } }