Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bfe28687 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

Bluetooth 5 enhanced scanning API

Bug: 30622771
Test: manual
Change-Id: I2c8065fbcedf48777ce18c7d8fe621e568b3fd75
(cherry picked from commit 9de522c6e48497028d36a1f8ad8f8adf4b7b1ae6)
parent eed95db0
Loading
Loading
Loading
Loading
+194 −11
Original line number Diff line number Diff line
@@ -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<ScanResult> CREATOR = new Creator<ScanResult>() {
+84 −2
Original line number Diff line number Diff line
@@ -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);
        }
    }
}