364 lines
12 KiB
Java
364 lines
12 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2014 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package android.bluetooth.le;
|
||
|
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.bluetooth.Attributable;
|
||
|
import android.bluetooth.BluetoothDevice;
|
||
|
import android.content.AttributionSource;
|
||
|
import android.os.Parcel;
|
||
|
import android.os.Parcelable;
|
||
|
|
||
|
import java.util.Objects;
|
||
|
|
||
|
/** ScanResult for Bluetooth LE scan. */
|
||
|
public final class ScanResult implements Parcelable, Attributable {
|
||
|
|
||
|
/**
|
||
|
* For chained advertisements, indicates that 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;
|
||
|
|
||
|
/** Advertising Set ID is not present in the packet. */
|
||
|
public static final int SID_NOT_PRESENT = 0xFF;
|
||
|
|
||
|
/** TX power is not present in the packet. */
|
||
|
public static final int TX_POWER_NOT_PRESENT = 0x7F;
|
||
|
|
||
|
/** Periodic advertising interval is not present in the packet. */
|
||
|
public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0x00;
|
||
|
|
||
|
/** Mask for checking whether event type represents legacy advertisement. */
|
||
|
private static final int ET_LEGACY_MASK = 0x10;
|
||
|
|
||
|
/** Mask for checking whether 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.
|
||
|
@Nullable private ScanRecord mScanRecord;
|
||
|
|
||
|
// Received signal strength.
|
||
|
private int mRssi;
|
||
|
|
||
|
// 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;
|
||
|
|
||
|
/**
|
||
|
* Constructs a new ScanResult.
|
||
|
*
|
||
|
* @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 Timestamp at which the scan result was observed.
|
||
|
* @deprecated use {@link #ScanResult(BluetoothDevice, int, int, int, int, int, int, int,
|
||
|
* ScanRecord, long)}
|
||
|
*/
|
||
|
@Deprecated
|
||
|
public ScanResult(
|
||
|
BluetoothDevice device, ScanRecord scanRecord, int rssi, long timestampNanos) {
|
||
|
mDevice = device;
|
||
|
mScanRecord = scanRecord;
|
||
|
mRssi = rssi;
|
||
|
mTimestampNanos = timestampNanos;
|
||
|
mEventType = (DATA_COMPLETE << 5) | ET_LEGACY_MASK | ET_CONNECTABLE_MASK;
|
||
|
mPrimaryPhy = BluetoothDevice.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) {
|
||
|
readFromParcel(in);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void writeToParcel(Parcel dest, int flags) {
|
||
|
if (mDevice != null) {
|
||
|
dest.writeInt(1);
|
||
|
mDevice.writeToParcel(dest, flags);
|
||
|
} else {
|
||
|
dest.writeInt(0);
|
||
|
}
|
||
|
if (mScanRecord != null) {
|
||
|
dest.writeInt(1);
|
||
|
dest.writeByteArray(mScanRecord.getBytes());
|
||
|
} else {
|
||
|
dest.writeInt(0);
|
||
|
}
|
||
|
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) {
|
||
|
if (in.readInt() == 1) {
|
||
|
mDevice = BluetoothDevice.CREATOR.createFromParcel(in);
|
||
|
}
|
||
|
if (in.readInt() == 1) {
|
||
|
mScanRecord = ScanRecord.parseFromBytes(in.createByteArray());
|
||
|
}
|
||
|
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
|
||
|
public int describeContents() {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public void setAttributionSource(@NonNull AttributionSource attributionSource) {
|
||
|
Attributable.setAttributionSource(mDevice, attributionSource);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the remote Bluetooth device identified by the Bluetooth device address. If the device
|
||
|
* is bonded, calling {@link BluetoothDevice#getAddress} on the object returned by this method
|
||
|
* will return the address that was originally bonded with (either identity address or random
|
||
|
* address).
|
||
|
*/
|
||
|
public BluetoothDevice getDevice() {
|
||
|
return mDevice;
|
||
|
}
|
||
|
|
||
|
/** Returns the scan record, which is a combination of advertisement and scan response. */
|
||
|
@Nullable
|
||
|
public ScanRecord getScanRecord() {
|
||
|
return mScanRecord;
|
||
|
}
|
||
|
|
||
|
/** Returns the received signal strength in dBm. The valid range is [-127, 126]. */
|
||
|
public int getRssi() {
|
||
|
return mRssi;
|
||
|
}
|
||
|
|
||
|
/** Returns timestamp since boot when the scan record was observed. */
|
||
|
public long getTimestampNanos() {
|
||
|
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 advertisement was received. Can be one of
|
||
|
* {@link BluetoothDevice#PHY_LE_1M} or {@link BluetoothDevice#PHY_LE_CODED}.
|
||
|
*/
|
||
|
public int getPrimaryPhy() {
|
||
|
return mPrimaryPhy;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the secondary Physical Layer on which this advertisement was received. Can be one of
|
||
|
* {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, {@link
|
||
|
* BluetoothDevice#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 {@link
|
||
|
* ScanResult#TX_POWER_NOT_PRESENT} indicates that the TX power is not present.
|
||
|
*/
|
||
|
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 {@link ScanResult#PERIODIC_INTERVAL_NOT_PRESENT} means
|
||
|
* periodic advertising interval is not present.
|
||
|
*/
|
||
|
public int getPeriodicAdvertisingInterval() {
|
||
|
return mPeriodicAdvertisingInterval;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
return Objects.hash(
|
||
|
mDevice,
|
||
|
mRssi,
|
||
|
mScanRecord,
|
||
|
mTimestampNanos,
|
||
|
mEventType,
|
||
|
mPrimaryPhy,
|
||
|
mSecondaryPhy,
|
||
|
mAdvertisingSid,
|
||
|
mTxPower,
|
||
|
mPeriodicAdvertisingInterval);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean equals(@Nullable Object obj) {
|
||
|
if (this == obj) {
|
||
|
return true;
|
||
|
}
|
||
|
if (obj == null || getClass() != obj.getClass()) {
|
||
|
return false;
|
||
|
}
|
||
|
ScanResult other = (ScanResult) obj;
|
||
|
return Objects.equals(mDevice, other.mDevice)
|
||
|
&& (mRssi == other.mRssi)
|
||
|
&& 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{"
|
||
|
+ "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 @android.annotation.NonNull Parcelable.Creator<ScanResult> CREATOR =
|
||
|
new Creator<ScanResult>() {
|
||
|
@Override
|
||
|
public ScanResult createFromParcel(Parcel source) {
|
||
|
return new ScanResult(source);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public ScanResult[] newArray(int size) {
|
||
|
return new ScanResult[size];
|
||
|
}
|
||
|
};
|
||
|
}
|