1066 lines
43 KiB
Java
1066 lines
43 KiB
Java
/*
|
|
* Copyright (C) 2017 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.net.wifi.rtt;
|
|
|
|
import android.annotation.ElapsedRealtimeLong;
|
|
import android.annotation.FlaggedApi;
|
|
import android.annotation.IntDef;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.annotation.SuppressLint;
|
|
import android.annotation.SystemApi;
|
|
import android.net.MacAddress;
|
|
import android.net.wifi.OuiKeyedData;
|
|
import android.net.wifi.ParcelUtil;
|
|
import android.net.wifi.ScanResult;
|
|
import android.net.wifi.WifiAnnotations.ChannelWidth;
|
|
import android.net.wifi.aware.PeerHandle;
|
|
import android.os.Build;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
|
|
import androidx.annotation.RequiresApi;
|
|
|
|
import com.android.modules.utils.build.SdkLevel;
|
|
import com.android.wifi.flags.Flags;
|
|
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
|
|
/**
|
|
* Ranging result for a request started by
|
|
* {@link WifiRttManager#startRanging(RangingRequest, java.util.concurrent.Executor, RangingResultCallback)}.
|
|
* Results are returned in {@link RangingResultCallback#onRangingResults(List)}.
|
|
* <p>
|
|
* A ranging result is the distance measurement result for a single device specified in the
|
|
* {@link RangingRequest}.
|
|
*/
|
|
public final class RangingResult implements Parcelable {
|
|
private static final String TAG = "RangingResult";
|
|
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
|
|
|
/** @hide */
|
|
@IntDef({STATUS_SUCCESS, STATUS_FAIL, STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface RangeResultStatus {
|
|
}
|
|
|
|
/**
|
|
* Individual range request status, {@link #getStatus()}. Indicates ranging operation was
|
|
* successful and distance value is valid.
|
|
*/
|
|
public static final int STATUS_SUCCESS = 0;
|
|
|
|
/**
|
|
* Individual range request status, {@link #getStatus()}. Indicates ranging operation failed
|
|
* and the distance value is invalid.
|
|
*/
|
|
public static final int STATUS_FAIL = 1;
|
|
|
|
/**
|
|
* Individual range request status, {@link #getStatus()}. Indicates that the ranging operation
|
|
* failed because the specified peer does not support IEEE 802.11mc RTT operations. Support by
|
|
* an Access Point can be confirmed using
|
|
* {@link android.net.wifi.ScanResult#is80211mcResponder()}.
|
|
* <p>
|
|
* On such a failure, the individual result fields of {@link RangingResult} such as
|
|
* {@link RangingResult#getDistanceMm()} are invalid.
|
|
*/
|
|
public static final int STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC = 2;
|
|
|
|
/**
|
|
* The unspecified value.
|
|
*/
|
|
public static final int UNSPECIFIED = -1;
|
|
|
|
private final @RangeResultStatus int mStatus;
|
|
private final MacAddress mMac;
|
|
private final PeerHandle mPeerHandle;
|
|
private final int mDistanceMm;
|
|
private final int mDistanceStdDevMm;
|
|
private final int mRssi;
|
|
private final int mNumAttemptedMeasurements;
|
|
private final int mNumSuccessfulMeasurements;
|
|
private final byte[] mLci;
|
|
private final byte[] mLcr;
|
|
private final ResponderLocation mResponderLocation;
|
|
private final long mTimestamp;
|
|
private final boolean mIs80211mcMeasurement;
|
|
private final int mFrequencyMHz;
|
|
private final int mPacketBw;
|
|
private final boolean mIs80211azNtbMeasurement;
|
|
private final long mNtbMinMeasurementTime;
|
|
private final long mNtbMaxMeasurementTime;
|
|
private final int mI2rTxLtfRepetitions;
|
|
private final int mR2iTxLtfRepetitions;
|
|
private final int mNumTxSpatialStreams;
|
|
private final int mNumRxSpatialStreams;
|
|
private List<OuiKeyedData> mVendorData;
|
|
|
|
/**
|
|
* Builder class used to construct {@link RangingResult} objects.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
public static final class Builder {
|
|
private @RangeResultStatus int mStatus = STATUS_FAIL;
|
|
private MacAddress mMac = null;
|
|
private PeerHandle mPeerHandle = null;
|
|
private int mDistanceMm = 0;
|
|
private int mDistanceStdDevMm = 0;
|
|
private int mRssi = -127;
|
|
private int mNumAttemptedMeasurements = 0;
|
|
private int mNumSuccessfulMeasurements = 0;
|
|
private byte[] mLci = null;
|
|
private byte[] mLcr = null;
|
|
private ResponderLocation mResponderLocation = null;
|
|
private long mTimestamp = 0;
|
|
private boolean mIs80211mcMeasurement = false;
|
|
private int mFrequencyMHz = UNSPECIFIED;
|
|
private int mPacketBw = UNSPECIFIED;
|
|
private boolean mIs80211azNtbMeasurement = false;
|
|
private long mNtbMinMeasurementTime = UNSPECIFIED;
|
|
private long mNtbMaxMeasurementTime = UNSPECIFIED;
|
|
private int mI2rTxLtfRepetitions = UNSPECIFIED;
|
|
private int mR2iTxLtfRepetitions = UNSPECIFIED;
|
|
private int mNumTxSpatialStreams = UNSPECIFIED;
|
|
private int mNumRxSpatialStreams = UNSPECIFIED;
|
|
private List<OuiKeyedData> mVendorData = Collections.emptyList();
|
|
|
|
/**
|
|
* Sets the Range result status.
|
|
*
|
|
* @param status Ranging result status, if not set defaults to
|
|
* {@link #STATUS_FAIL}.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setStatus(@RangeResultStatus int status) {
|
|
mStatus = status;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the MAC address of the ranging result.
|
|
*
|
|
* @param macAddress Mac address, if not defaults to null.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setMacAddress(@Nullable MacAddress macAddress) {
|
|
mMac = macAddress;
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets the peer handle. Applicable only for NAN Ranging.
|
|
*
|
|
* @param peerHandle Opaque object used to represent a Wi-Fi Aware peer. If not set,
|
|
* defaults to null.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setPeerHandle(@Nullable PeerHandle peerHandle) {
|
|
mPeerHandle = peerHandle;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the distance in millimeter.
|
|
*
|
|
* @param distanceMm distance. If not set, defaults to 0.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setDistanceMm(int distanceMm) {
|
|
mDistanceMm = distanceMm;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the standard deviation of the distance in millimeter.
|
|
*
|
|
* @param distanceStdDevMm Standard deviation of the distance measurement. If not set
|
|
* defaults to 0.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setDistanceStdDevMm(int distanceStdDevMm) {
|
|
mDistanceStdDevMm = distanceStdDevMm;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the average RSSI.
|
|
*
|
|
* @param rssi Average RSSI. If not set, defaults to -127.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setRssi(int rssi) {
|
|
mRssi = rssi;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the total number of RTT measurements attempted.
|
|
*
|
|
* @param numAttemptedMeasurements Number of attempted measurements. If not set, default
|
|
* to 0.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setNumAttemptedMeasurements(int numAttemptedMeasurements) {
|
|
mNumAttemptedMeasurements = numAttemptedMeasurements;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the total number of successful RTT measurements.
|
|
*
|
|
* @param numSuccessfulMeasurements Number of successful measurements. If not set, default
|
|
* to 0.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setNumSuccessfulMeasurements(int numSuccessfulMeasurements) {
|
|
mNumSuccessfulMeasurements = numSuccessfulMeasurements;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the Location Configuration Information (LCI).
|
|
*
|
|
* LCI provides data about the access point's (AP) physical location, such as its
|
|
* latitude, longitude, and altitude. The format is specified in the IEEE 802.11-2016
|
|
* specifications, section 9.4.2.22.10.
|
|
*
|
|
* @param lci Location configuration information. If not set, defaults to null.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setLci(@Nullable byte[] lci) {
|
|
mLci = lci;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the Location Civic Report (LCR).
|
|
*
|
|
* LCR provides additional details about the AP's location in a human-readable format,
|
|
* such as the street address, building name, or floor number. This can be helpful for
|
|
* users to understand the context of their location within a building or complex.
|
|
*
|
|
* The format is
|
|
* specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.13.
|
|
*
|
|
* @param lcr Location civic report. If not set, defaults to null.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setLcr(@Nullable byte[] lcr) {
|
|
mLcr = lcr;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets Responder Location.
|
|
*
|
|
* ResponderLocation is both a Location Configuration Information (LCI) decoder and a
|
|
* Location Civic Report (LCR) decoder for information received from a Wi-Fi Access Point
|
|
* (AP) during Wi-Fi RTT ranging process.
|
|
*
|
|
* @param responderLocation Responder location. If not set, defaults to null.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setUnverifiedResponderLocation(
|
|
@Nullable ResponderLocation responderLocation) {
|
|
mResponderLocation = responderLocation;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the time stamp at which the ranging operation was performed.
|
|
*
|
|
* The timestamp is in milliseconds since boot, including time spent in sleep,
|
|
* corresponding to values provided by {@link android.os.SystemClock#elapsedRealtime()}.
|
|
*
|
|
* @param timestamp time stamp in milliseconds. If not set, default to 0.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setRangingTimestampMillis(@ElapsedRealtimeLong long timestamp) {
|
|
mTimestamp = timestamp;
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets whether the ranging measurement was performed using IEEE 802.11mc ranging method.
|
|
* If {@link #set80211mcMeasurement(boolean)} is set as false and
|
|
* {@link #set80211azNtbMeasurement(boolean)} is also set as false, ranging measurement was
|
|
* performed using one-side RTT. If not set, default to false.
|
|
*
|
|
* @param is80211mcMeasurement true for IEEE 802.11mc measure, otherwise false.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder set80211mcMeasurement(boolean is80211mcMeasurement) {
|
|
mIs80211mcMeasurement = is80211mcMeasurement;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the center frequency of the primary 20 MHz frequency (in MHz) of the channel over
|
|
* which the measurement frames are sent. If not set, default to
|
|
* {@link RangingResult#UNSPECIFIED}
|
|
*
|
|
* @param frequencyMHz Frequency.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setMeasurementChannelFrequencyMHz(int frequencyMHz) {
|
|
mFrequencyMHz = frequencyMHz;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the bandwidth used to transmit the RTT measurement frame. If not set, default to
|
|
* {@link RangingResult#UNSPECIFIED}.
|
|
*
|
|
* @param measurementBandwidth Measurement bandwidth.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setMeasurementBandwidth(@ChannelWidth int measurementBandwidth) {
|
|
mPacketBw = measurementBandwidth;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets whether the ranging measurement was performed using IEEE 802.11az non-trigger
|
|
* ranging method. If {@link #set80211azNtbMeasurement(boolean)} is set as false and
|
|
* {@link #set80211mcMeasurement(boolean)} is also set as false, ranging measurement was
|
|
* performed using one-side RTT. If not set defaults to false.
|
|
*
|
|
* @param is80211azNtbMeasurement true for IEEE 802.11az non-trigger based measurement,
|
|
* otherwise false.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder set80211azNtbMeasurement(boolean is80211azNtbMeasurement) {
|
|
mIs80211azNtbMeasurement = is80211azNtbMeasurement;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets minimum time between measurements in microseconds for IEEE 802.11az non-trigger
|
|
* based ranging. If not set, defaults to {@link RangingResult#UNSPECIFIED}.
|
|
*
|
|
* @param ntbMinMeasurementTime non-trigger based ranging minimum measurement time.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setMinTimeBetweenNtbMeasurementsMicros(long ntbMinMeasurementTime) {
|
|
mNtbMinMeasurementTime = ntbMinMeasurementTime;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets maximum time between measurements in microseconds for IEEE 802.11az non-trigger
|
|
* based ranging. If not set, defaults to {@link RangingResult#UNSPECIFIED}.
|
|
*
|
|
* @param ntbMaxMeasurementTime non-trigger based ranging maximum measurement time.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder setMaxTimeBetweenNtbMeasurementsMicros(long ntbMaxMeasurementTime) {
|
|
mNtbMaxMeasurementTime = ntbMaxMeasurementTime;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets LTF repetitions that the initiator station used in the preamble. If not set,
|
|
* defaults to {@link RangingResult#UNSPECIFIED}.
|
|
*
|
|
* @param i2rTxLtfRepetitions LFT repetition count.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder set80211azInitiatorTxLtfRepetitionsCount(int i2rTxLtfRepetitions) {
|
|
mI2rTxLtfRepetitions = i2rTxLtfRepetitions;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets LTF repetitions that the responder station used in the preamble. If not set,
|
|
* defaults to {@link RangingResult#UNSPECIFIED}.
|
|
*
|
|
* @param r2iTxLtfRepetitions LFT repetition count.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder set80211azResponderTxLtfRepetitionsCount(int r2iTxLtfRepetitions) {
|
|
mR2iTxLtfRepetitions = r2iTxLtfRepetitions;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets number of transmit spatial streams that the initiator station used for the
|
|
* ranging result. If not set, defaults to {@link RangingResult#UNSPECIFIED}.
|
|
*
|
|
* @param numTxSpatialStreams Number of transmit spatial streams.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder set80211azNumberOfTxSpatialStreams(int numTxSpatialStreams) {
|
|
mNumTxSpatialStreams = numTxSpatialStreams;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets number of receive spatial streams that the initiator station used for the ranging
|
|
* result. If not set, defaults to {@link RangingResult#UNSPECIFIED}.
|
|
*
|
|
* @param numRxSpatialStreams Number of receive spatial streams.
|
|
* @return The builder to facilitate chaining.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public Builder set80211azNumberOfRxSpatialStreams(int numRxSpatialStreams) {
|
|
mNumRxSpatialStreams = numRxSpatialStreams;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set additional vendor-provided configuration data.
|
|
*
|
|
* @param vendorData List of {@link android.net.wifi.OuiKeyedData} containing the
|
|
* vendor-provided configuration data. Note that multiple elements with
|
|
* the same OUI are allowed.
|
|
* @hide
|
|
*/
|
|
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@SystemApi
|
|
@NonNull
|
|
public Builder setVendorData(@NonNull List<OuiKeyedData> vendorData) {
|
|
if (!SdkLevel.isAtLeastV()) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
if (vendorData == null) {
|
|
throw new IllegalArgumentException("setVendorData received a null value");
|
|
}
|
|
mVendorData = vendorData;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Build {@link RangingResult}
|
|
* @return an instance of {@link RangingResult}
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@NonNull
|
|
public RangingResult build() {
|
|
if (mMac == null && mPeerHandle == null) {
|
|
throw new IllegalArgumentException("Either MAC address or Peer handle is needed");
|
|
}
|
|
if (mIs80211azNtbMeasurement && mIs80211mcMeasurement) {
|
|
throw new IllegalArgumentException(
|
|
"A ranging result cannot use both IEEE 802.11mc and IEEE 802.11az "
|
|
+ "measurements simultaneously");
|
|
}
|
|
return new RangingResult(this);
|
|
}
|
|
}
|
|
|
|
/** @hide */
|
|
private RangingResult(Builder builder) {
|
|
mStatus = builder.mStatus;
|
|
mMac = builder.mMac;
|
|
mPeerHandle = builder.mPeerHandle;
|
|
mDistanceMm = builder.mDistanceMm;
|
|
mDistanceStdDevMm = builder.mDistanceStdDevMm;
|
|
mRssi = builder.mRssi;
|
|
mNumAttemptedMeasurements = builder.mNumAttemptedMeasurements;
|
|
mNumSuccessfulMeasurements = builder.mNumSuccessfulMeasurements;
|
|
mLci = (builder.mLci == null) ? EMPTY_BYTE_ARRAY : builder.mLci;
|
|
mLcr = (builder.mLcr == null) ? EMPTY_BYTE_ARRAY : builder.mLcr;
|
|
mResponderLocation = builder.mResponderLocation;
|
|
mTimestamp = builder.mTimestamp;
|
|
mIs80211mcMeasurement = builder.mIs80211mcMeasurement;
|
|
mFrequencyMHz = builder.mFrequencyMHz;
|
|
mPacketBw = builder.mPacketBw;
|
|
mIs80211azNtbMeasurement = builder.mIs80211azNtbMeasurement;
|
|
mNtbMinMeasurementTime = builder.mNtbMinMeasurementTime;
|
|
mNtbMaxMeasurementTime = builder.mNtbMaxMeasurementTime;
|
|
mI2rTxLtfRepetitions = builder.mI2rTxLtfRepetitions;
|
|
mR2iTxLtfRepetitions = builder.mR2iTxLtfRepetitions;
|
|
mNumRxSpatialStreams = builder.mNumRxSpatialStreams;
|
|
mNumTxSpatialStreams = builder.mNumTxSpatialStreams;
|
|
mVendorData = builder.mVendorData;
|
|
}
|
|
|
|
/**
|
|
* @return The status of ranging measurement: {@link #STATUS_SUCCESS} in case of success, and
|
|
* {@link #STATUS_FAIL} in case of failure.
|
|
*/
|
|
@RangeResultStatus
|
|
public int getStatus() {
|
|
return mStatus;
|
|
}
|
|
|
|
/**
|
|
* @return The MAC address of the device whose range measurement was requested. Will correspond
|
|
* to the MAC address of the device in the {@link RangingRequest}.
|
|
* <p>
|
|
* Will return a {@code null} for results corresponding to requests issued using a {@code
|
|
* PeerHandle}, i.e. using the {@link RangingRequest.Builder#addWifiAwarePeer(PeerHandle)} API.
|
|
*/
|
|
@Nullable
|
|
public MacAddress getMacAddress() {
|
|
return mMac;
|
|
}
|
|
|
|
/**
|
|
* @return The PeerHandle of the device whose reange measurement was requested. Will correspond
|
|
* to the PeerHandle of the devices requested using
|
|
* {@link RangingRequest.Builder#addWifiAwarePeer(PeerHandle)}.
|
|
* <p>
|
|
* Will return a {@code null} for results corresponding to requests issued using a MAC address.
|
|
*/
|
|
@Nullable public PeerHandle getPeerHandle() {
|
|
return mPeerHandle;
|
|
}
|
|
|
|
/**
|
|
* @return The distance (in mm) to the device specified by {@link #getMacAddress()} or
|
|
* {@link #getPeerHandle()}.
|
|
* <p>
|
|
* Note: the measured distance may be negative for very close devices.
|
|
* <p>
|
|
* Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
|
|
* exception.
|
|
*/
|
|
public int getDistanceMm() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"getDistanceMm(): invoked on an invalid result: getStatus()=" + mStatus);
|
|
}
|
|
return mDistanceMm;
|
|
}
|
|
|
|
/**
|
|
* @return The standard deviation of the measured distance (in mm) to the device specified by
|
|
* {@link #getMacAddress()} or {@link #getPeerHandle()}. The standard deviation is calculated
|
|
* over the measurements executed in a single RTT burst. The number of measurements is returned
|
|
* by {@link #getNumSuccessfulMeasurements()} - 0 successful measurements indicate that the
|
|
* standard deviation is not valid (a valid standard deviation requires at least 2 data points).
|
|
* <p>
|
|
* Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
|
|
* exception.
|
|
*/
|
|
public int getDistanceStdDevMm() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"getDistanceStdDevMm(): invoked on an invalid result: getStatus()=" + mStatus);
|
|
}
|
|
return mDistanceStdDevMm;
|
|
}
|
|
|
|
/**
|
|
* @return The average RSSI, in units of dBm, observed during the RTT measurement.
|
|
* <p>
|
|
* Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
|
|
* exception.
|
|
*/
|
|
public int getRssi() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"getRssi(): invoked on an invalid result: getStatus()=" + mStatus);
|
|
}
|
|
return mRssi;
|
|
}
|
|
|
|
/**
|
|
* @return The number of attempted measurements used in the RTT exchange resulting in this set
|
|
* of results. The number of successful measurements is returned by
|
|
* {@link #getNumSuccessfulMeasurements()} which at most, if there are no errors, will be 1
|
|
* less than the number of attempted measurements.
|
|
* <p>
|
|
* Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
|
|
* exception. If the value is 0, it should be interpreted as no information available, which may
|
|
* occur for one-sided RTT measurements. Instead {@link RangingRequest#getRttBurstSize()}
|
|
* should be used instead.
|
|
*/
|
|
public int getNumAttemptedMeasurements() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"getNumAttemptedMeasurements(): invoked on an invalid result: getStatus()="
|
|
+ mStatus);
|
|
}
|
|
return mNumAttemptedMeasurements;
|
|
}
|
|
|
|
/**
|
|
* @return The number of successful measurements used to calculate the distance and standard
|
|
* deviation. If the number of successful measurements if 1 then then standard deviation,
|
|
* returned by {@link #getDistanceStdDevMm()}, is not valid (a 0 is returned for the standard
|
|
* deviation).
|
|
* <p>
|
|
* The total number of measurement attempts is returned by
|
|
* {@link #getNumAttemptedMeasurements()}. The number of successful measurements will be at
|
|
* most 1 less then the number of attempted measurements.
|
|
* <p>
|
|
* Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
|
|
* exception.
|
|
*/
|
|
public int getNumSuccessfulMeasurements() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"getNumSuccessfulMeasurements(): invoked on an invalid result: getStatus()="
|
|
+ mStatus);
|
|
}
|
|
return mNumSuccessfulMeasurements;
|
|
}
|
|
|
|
/**
|
|
* @return The unverified responder location represented as {@link ResponderLocation} which
|
|
* captures location information the responder is programmed to broadcast. The responder
|
|
* location is referred to as unverified, because we are relying on the device/site
|
|
* administrator to correctly configure its location data.
|
|
* <p>
|
|
* Will return a {@code null} when the location information cannot be parsed.
|
|
* <p>
|
|
* Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
|
|
* exception.
|
|
*/
|
|
@Nullable
|
|
public ResponderLocation getUnverifiedResponderLocation() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"getUnverifiedResponderLocation(): invoked on an invalid result: getStatus()="
|
|
+ mStatus);
|
|
}
|
|
return mResponderLocation;
|
|
}
|
|
|
|
/**
|
|
* @return The Location Configuration Information (LCI) as self-reported by the peer. The format
|
|
* is specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.10.
|
|
* <p>
|
|
* Note: the information is NOT validated - use with caution. Consider validating it with
|
|
* other sources of information before using it.
|
|
*/
|
|
@SuppressLint("UnflaggedApi") // Flagging API promotion from @SystemApi to public not supported
|
|
@NonNull
|
|
public byte[] getLci() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"getLci(): invoked on an invalid result: getStatus()=" + mStatus);
|
|
}
|
|
return mLci;
|
|
}
|
|
|
|
/**
|
|
* @return The Location Civic report (LCR) as self-reported by the peer. The format
|
|
* is specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.13.
|
|
* <p>
|
|
* Note: the information is NOT validated - use with caution. Consider validating it with
|
|
* other sources of information before using it.
|
|
*/
|
|
@SuppressLint("UnflaggedApi") // Flagging API promotion from @SystemApi to public not supported
|
|
@NonNull
|
|
public byte[] getLcr() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"getReportedLocationCivic(): invoked on an invalid result: getStatus()="
|
|
+ mStatus);
|
|
}
|
|
return mLcr;
|
|
}
|
|
|
|
/**
|
|
* @return The timestamp at which the ranging operation was performed. The timestamp is in
|
|
* milliseconds since boot, including time spent in sleep, corresponding to values provided by
|
|
* {@link android.os.SystemClock#elapsedRealtime()}.
|
|
* <p>
|
|
* Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
|
|
* exception.
|
|
*/
|
|
public long getRangingTimestampMillis() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"getRangingTimestampMillis(): invoked on an invalid result: getStatus()="
|
|
+ mStatus);
|
|
}
|
|
return mTimestamp;
|
|
}
|
|
|
|
/**
|
|
* @return The result is true if the IEEE 802.11mc protocol was used. If the result is false,
|
|
* and {@link #is80211azNtbMeasurement()} is also false a one-side RTT result is provided
|
|
* which does not subtract the turnaround time at the responder.
|
|
* <p>
|
|
* Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
|
|
* exception.
|
|
*/
|
|
public boolean is80211mcMeasurement() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"is80211mcMeasurementResult(): invoked on an invalid result: getStatus()="
|
|
+ mStatus);
|
|
}
|
|
return mIs80211mcMeasurement;
|
|
}
|
|
|
|
/**
|
|
* @return The result is true if the IEEE 802.11az non-trigger based protocol was used. If the
|
|
* result is false, and {@link #is80211mcMeasurement()} is also false a one-side RTT result
|
|
* is provided which does not subtract the turnaround time at the responder.
|
|
* <p>.
|
|
* Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
|
|
* exception.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
public boolean is80211azNtbMeasurement() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"is80211azNtbMeasurement(): invoked on an invalid result: getStatus()="
|
|
+ mStatus);
|
|
}
|
|
return mIs80211azNtbMeasurement;
|
|
}
|
|
|
|
/**
|
|
* Gets minimum time between measurements in microseconds for IEEE 802.11az non-trigger based
|
|
* ranging.
|
|
*
|
|
* The next 11az ranging measurement request must be invoked after the minimum time from the
|
|
* last measurement time {@link #getRangingTimestampMillis()} for the peer. Otherwise, cached
|
|
* ranging result will be returned for the peer.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
public long getMinTimeBetweenNtbMeasurementsMicros() {
|
|
return mNtbMinMeasurementTime;
|
|
}
|
|
|
|
/**
|
|
* Gets maximum time between measurements in microseconds for IEEE 802.11az non-trigger based
|
|
* ranging.
|
|
*
|
|
* The next 11az ranging request needs to be invoked before the maximum time from the last
|
|
* measurement time {@link #getRangingTimestampMillis()}. Otherwise, the non-trigger based
|
|
* ranging session will be terminated and a new ranging negotiation will happen with
|
|
* the responding station.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
public long getMaxTimeBetweenNtbMeasurementsMicros() {
|
|
return mNtbMaxMeasurementTime;
|
|
}
|
|
|
|
/**
|
|
* Gets LTF repetitions that the responder station (RSTA) used in the preamble of the
|
|
* responder to initiator (I2R) null data PPDU (NDP) for this result.
|
|
*
|
|
* LTF repetitions is the multiple transmissions of HE-LTF symbols in an HE ranging NDP. An
|
|
* HE-LTF repetition value of 1 indicates no repetitions.
|
|
*
|
|
* @return LTF repetitions count
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
public int get80211azResponderTxLtfRepetitionsCount() {
|
|
return mR2iTxLtfRepetitions;
|
|
}
|
|
|
|
/**
|
|
* Gets LTF repetitions that the initiator station (ISTA) used in the preamble of the
|
|
* initiator to responder (I2R) null data PPDU (NDP) for this result.
|
|
*
|
|
* LTF repetitions is the multiple transmissions of HE-LTF symbols in an HE ranging NDP. An
|
|
* HE-LTF repetition value of 1 indicates no repetitions.
|
|
*
|
|
* @return LTF repetitions count
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
public int get80211azInitiatorTxLtfRepetitionsCount() {
|
|
return mI2rTxLtfRepetitions;
|
|
}
|
|
|
|
/**
|
|
* Gets number of transmit spatial streams that the initiator station (ISTA) used for the
|
|
* initiator to responder (I2R) null data PPDU (NDP) for this result.
|
|
*
|
|
* @return Number of spatial streams
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
public int get80211azNumberOfTxSpatialStreams() {
|
|
return mNumTxSpatialStreams;
|
|
}
|
|
|
|
/**
|
|
* Gets number of receive spatial streams that the initiator station (ISTA) used for the
|
|
* initiator to responder (I2R) null data PPDU (NDP) for this result.
|
|
*
|
|
* @return Number of spatial streams
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
public int get80211azNumberOfRxSpatialStreams() {
|
|
return mNumRxSpatialStreams;
|
|
}
|
|
|
|
/**
|
|
* The center frequency of the primary 20 MHz frequency (in MHz) of the channel over
|
|
* which the measurement frames are sent.
|
|
* @return center frequency in Mhz of the channel if available, otherwise {@link #UNSPECIFIED}
|
|
* is returned.
|
|
* <p>
|
|
* @throws IllegalStateException if {@link #getStatus()} does not return
|
|
* {@link #STATUS_SUCCESS}.
|
|
*/
|
|
public int getMeasurementChannelFrequencyMHz() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"getMeasurementChannelFrequencyMHz():"
|
|
+ " invoked on an invalid result: getStatus()= " + mStatus);
|
|
}
|
|
return mFrequencyMHz;
|
|
}
|
|
|
|
/**
|
|
* The bandwidth used to transmit the RTT measurement frame.
|
|
* @return one of {@link ScanResult#CHANNEL_WIDTH_20MHZ},
|
|
* {@link ScanResult#CHANNEL_WIDTH_40MHZ},
|
|
* {@link ScanResult#CHANNEL_WIDTH_80MHZ}, {@link ScanResult#CHANNEL_WIDTH_160MHZ},
|
|
* {@link ScanResult #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link ScanResult #CHANNEL_WIDTH_320MHZ}
|
|
* if available, otherwise {@link #UNSPECIFIED} is returned.
|
|
* <p>
|
|
* @throws IllegalStateException if {@link #getStatus()} does not return
|
|
* {@link #STATUS_SUCCESS}.
|
|
*/
|
|
public @ChannelWidth int getMeasurementBandwidth() {
|
|
if (mStatus != STATUS_SUCCESS) {
|
|
throw new IllegalStateException(
|
|
"getMeasurementBandwidth(): invoked on an invalid result: getStatus()="
|
|
+ mStatus);
|
|
}
|
|
return mPacketBw;
|
|
}
|
|
|
|
/**
|
|
* Get the vendor-provided configuration data, if it exists.
|
|
*
|
|
* @return Vendor configuration data, or empty list if it does not exist.
|
|
* @hide
|
|
*/
|
|
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|
@SystemApi
|
|
@NonNull
|
|
public List<OuiKeyedData> getVendorData() {
|
|
if (!SdkLevel.isAtLeastV()) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
return mVendorData;
|
|
}
|
|
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public void writeToParcel(Parcel dest, int flags) {
|
|
dest.writeInt(mStatus);
|
|
if (mMac == null) {
|
|
dest.writeBoolean(false);
|
|
} else {
|
|
dest.writeBoolean(true);
|
|
mMac.writeToParcel(dest, flags);
|
|
}
|
|
if (mPeerHandle == null) {
|
|
dest.writeBoolean(false);
|
|
} else {
|
|
dest.writeBoolean(true);
|
|
dest.writeInt(mPeerHandle.peerId);
|
|
}
|
|
dest.writeInt(mDistanceMm);
|
|
dest.writeInt(mDistanceStdDevMm);
|
|
dest.writeInt(mRssi);
|
|
dest.writeInt(mNumAttemptedMeasurements);
|
|
dest.writeInt(mNumSuccessfulMeasurements);
|
|
dest.writeByteArray(mLci);
|
|
dest.writeByteArray(mLcr);
|
|
dest.writeParcelable(mResponderLocation, flags);
|
|
dest.writeLong(mTimestamp);
|
|
dest.writeBoolean(mIs80211mcMeasurement);
|
|
dest.writeInt(mFrequencyMHz);
|
|
dest.writeInt(mPacketBw);
|
|
dest.writeBoolean(mIs80211azNtbMeasurement);
|
|
dest.writeLong(mNtbMinMeasurementTime);
|
|
dest.writeLong(mNtbMaxMeasurementTime);
|
|
dest.writeInt(mI2rTxLtfRepetitions);
|
|
dest.writeInt(mR2iTxLtfRepetitions);
|
|
dest.writeInt(mNumTxSpatialStreams);
|
|
dest.writeInt(mNumRxSpatialStreams);
|
|
if (SdkLevel.isAtLeastV()) {
|
|
dest.writeList(mVendorData);
|
|
}
|
|
}
|
|
|
|
public static final @android.annotation.NonNull Creator<RangingResult> CREATOR =
|
|
new Creator<RangingResult>() {
|
|
@Override
|
|
public RangingResult[] newArray(int size) {
|
|
return new RangingResult[size];
|
|
}
|
|
|
|
@Override
|
|
public RangingResult createFromParcel(Parcel in) {
|
|
RangingResult.Builder builder = new Builder()
|
|
.setStatus(in.readInt())
|
|
.setMacAddress(
|
|
in.readBoolean() ? MacAddress.CREATOR.createFromParcel(in)
|
|
: null)
|
|
.setPeerHandle(in.readBoolean() ? new PeerHandle(in.readInt()) : null)
|
|
.setDistanceMm(in.readInt())
|
|
.setDistanceStdDevMm(in.readInt())
|
|
.setRssi(in.readInt())
|
|
.setNumAttemptedMeasurements(in.readInt())
|
|
.setNumSuccessfulMeasurements(in.readInt())
|
|
.setLci(in.createByteArray())
|
|
.setLcr(in.createByteArray())
|
|
.setUnverifiedResponderLocation(
|
|
in.readParcelable(this.getClass().getClassLoader()))
|
|
.setRangingTimestampMillis(in.readLong())
|
|
.set80211mcMeasurement(in.readBoolean())
|
|
.setMeasurementChannelFrequencyMHz(in.readInt())
|
|
.setMeasurementBandwidth(in.readInt())
|
|
.set80211azNtbMeasurement(in.readBoolean())
|
|
.setMinTimeBetweenNtbMeasurementsMicros(in.readLong())
|
|
.setMaxTimeBetweenNtbMeasurementsMicros(in.readLong())
|
|
.set80211azInitiatorTxLtfRepetitionsCount(in.readInt())
|
|
.set80211azResponderTxLtfRepetitionsCount(in.readInt())
|
|
.set80211azNumberOfTxSpatialStreams(in.readInt())
|
|
.set80211azNumberOfRxSpatialStreams(in.readInt());
|
|
if (SdkLevel.isAtLeastV()) {
|
|
builder.setVendorData(ParcelUtil.readOuiKeyedDataList(in));
|
|
}
|
|
return builder.build();
|
|
}
|
|
};
|
|
|
|
/** @hide */
|
|
@Override
|
|
public String toString() {
|
|
return new StringBuilder("RangingResult: [status=").append(mStatus)
|
|
.append(", mac=").append(mMac)
|
|
.append(", peerHandle=").append(
|
|
mPeerHandle == null ? "<null>" : mPeerHandle.peerId)
|
|
.append(", distanceMm=").append(mDistanceMm)
|
|
.append(", distanceStdDevMm=").append(mDistanceStdDevMm)
|
|
.append(", rssi=").append(mRssi)
|
|
.append(", numAttemptedMeasurements=").append(mNumAttemptedMeasurements)
|
|
.append(", numSuccessfulMeasurements=").append(mNumSuccessfulMeasurements)
|
|
.append(", lci=").append(Arrays.toString(mLci))
|
|
.append(", lcr=").append(Arrays.toString(mLcr))
|
|
.append(", responderLocation=").append(mResponderLocation)
|
|
.append(", timestamp=").append(mTimestamp).append(", is80211mcMeasurement=")
|
|
.append(mIs80211mcMeasurement)
|
|
.append(", frequencyMHz=").append(mFrequencyMHz)
|
|
.append(", packetBw=").append(mPacketBw)
|
|
.append("is80211azNtbMeasurement").append(mIs80211azNtbMeasurement)
|
|
.append("ntbMinMeasurementTime").append(mNtbMinMeasurementTime)
|
|
.append("ntbMaxMeasurementTime").append(mNtbMaxMeasurementTime)
|
|
.append("i2rTxLtfRepetitions").append(mI2rTxLtfRepetitions)
|
|
.append("r2iTxLtfRepetitions").append(mR2iTxLtfRepetitions)
|
|
.append("txSpatialStreams").append(mNumTxSpatialStreams)
|
|
.append("rxSpatialStreams").append(mNumRxSpatialStreams)
|
|
.append(", vendorData=").append(mVendorData)
|
|
.append("]").toString();
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (this == o) {
|
|
return true;
|
|
}
|
|
|
|
if (!(o instanceof RangingResult)) {
|
|
return false;
|
|
}
|
|
|
|
RangingResult lhs = (RangingResult) o;
|
|
|
|
return mStatus == lhs.mStatus && Objects.equals(mMac, lhs.mMac) && Objects.equals(
|
|
mPeerHandle, lhs.mPeerHandle) && mDistanceMm == lhs.mDistanceMm
|
|
&& mDistanceStdDevMm == lhs.mDistanceStdDevMm && mRssi == lhs.mRssi
|
|
&& mNumAttemptedMeasurements == lhs.mNumAttemptedMeasurements
|
|
&& mNumSuccessfulMeasurements == lhs.mNumSuccessfulMeasurements
|
|
&& Arrays.equals(mLci, lhs.mLci) && Arrays.equals(mLcr, lhs.mLcr)
|
|
&& mTimestamp == lhs.mTimestamp
|
|
&& mIs80211mcMeasurement == lhs.mIs80211mcMeasurement
|
|
&& Objects.equals(mResponderLocation, lhs.mResponderLocation)
|
|
&& mFrequencyMHz == lhs.mFrequencyMHz
|
|
&& mPacketBw == lhs.mPacketBw
|
|
&& mIs80211azNtbMeasurement == lhs.mIs80211azNtbMeasurement
|
|
&& mNtbMinMeasurementTime == lhs.mNtbMinMeasurementTime
|
|
&& mNtbMaxMeasurementTime == lhs.mNtbMaxMeasurementTime
|
|
&& mI2rTxLtfRepetitions == lhs.mI2rTxLtfRepetitions
|
|
&& mR2iTxLtfRepetitions == lhs.mR2iTxLtfRepetitions
|
|
&& mNumTxSpatialStreams == lhs.mNumTxSpatialStreams
|
|
&& mNumRxSpatialStreams == lhs.mNumRxSpatialStreams
|
|
&& Objects.equals(mVendorData, lhs.mVendorData);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(mStatus, mMac, mPeerHandle, mDistanceMm, mDistanceStdDevMm, mRssi,
|
|
mNumAttemptedMeasurements, mNumSuccessfulMeasurements, Arrays.hashCode(mLci),
|
|
Arrays.hashCode(mLcr), mResponderLocation, mTimestamp, mIs80211mcMeasurement,
|
|
mFrequencyMHz, mPacketBw, mIs80211azNtbMeasurement, mNtbMinMeasurementTime,
|
|
mNtbMaxMeasurementTime, mI2rTxLtfRepetitions, mR2iTxLtfRepetitions,
|
|
mNumTxSpatialStreams, mR2iTxLtfRepetitions, mVendorData);
|
|
}
|
|
}
|