1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
|
/*
* 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.Nullable;
import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
/**
* ScanResult for Bluetooth LE scan.
*/
public final class ScanResult implements Parcelable {
/**
* 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;
/**
* 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;
}
/**
* Returns the remote Bluetooth device identified by the Bluetooth device 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 advertisment 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 advertisment 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(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];
}
};
}
|