551 lines
20 KiB
Java
551 lines
20 KiB
Java
![]() |
/*
|
||
|
* Copyright 2020 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.uwb;
|
||
|
|
||
|
import android.annotation.IntDef;
|
||
|
import android.annotation.IntRange;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.annotation.SuppressLint;
|
||
|
import android.annotation.SystemApi;
|
||
|
import android.os.Parcel;
|
||
|
import android.os.Parcelable;
|
||
|
import android.os.PersistableBundle;
|
||
|
import android.os.SystemClock;
|
||
|
import android.uwb.util.PersistableBundleUtils;
|
||
|
|
||
|
import java.lang.annotation.Retention;
|
||
|
import java.lang.annotation.RetentionPolicy;
|
||
|
import java.util.Objects;
|
||
|
|
||
|
/**
|
||
|
* Representation of a ranging measurement between the local device and a remote device
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
public final class RangingMeasurement implements Parcelable {
|
||
|
public static final int RSSI_UNKNOWN = -128;
|
||
|
public static final int RSSI_MIN = -127;
|
||
|
public static final int RSSI_MAX = -1;
|
||
|
|
||
|
private final UwbAddress mRemoteDeviceAddress;
|
||
|
private final @Status int mStatus;
|
||
|
private final long mElapsedRealtimeNanos;
|
||
|
private final DistanceMeasurement mDistanceMeasurement;
|
||
|
private final AngleOfArrivalMeasurement mAngleOfArrivalMeasurement;
|
||
|
private final AngleOfArrivalMeasurement mDestinationAngleOfArrivalMeasurement;
|
||
|
private final @LineOfSight int mLineOfSight;
|
||
|
private final @MeasurementFocus int mMeasurementFocus;
|
||
|
private final int mRssiDbm;
|
||
|
private final PersistableBundle mRangingMeasurementMetadata;
|
||
|
|
||
|
private RangingMeasurement(@NonNull UwbAddress remoteDeviceAddress, @Status int status,
|
||
|
long elapsedRealtimeNanos, @Nullable DistanceMeasurement distanceMeasurement,
|
||
|
@Nullable AngleOfArrivalMeasurement angleOfArrivalMeasurement,
|
||
|
@Nullable AngleOfArrivalMeasurement destinationAngleOfArrivalMeasurement,
|
||
|
@LineOfSight int lineOfSight, @MeasurementFocus int measurementFocus,
|
||
|
@IntRange(from = RSSI_UNKNOWN, to = RSSI_MAX) int rssiDbm,
|
||
|
PersistableBundle rangingMeasurementMetadata) {
|
||
|
mRemoteDeviceAddress = remoteDeviceAddress;
|
||
|
mStatus = status;
|
||
|
mElapsedRealtimeNanos = elapsedRealtimeNanos;
|
||
|
mDistanceMeasurement = distanceMeasurement;
|
||
|
mAngleOfArrivalMeasurement = angleOfArrivalMeasurement;
|
||
|
mDestinationAngleOfArrivalMeasurement = destinationAngleOfArrivalMeasurement;
|
||
|
mLineOfSight = lineOfSight;
|
||
|
mMeasurementFocus = measurementFocus;
|
||
|
mRssiDbm = rssiDbm;
|
||
|
mRangingMeasurementMetadata = rangingMeasurementMetadata;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the remote device's {@link UwbAddress}
|
||
|
*
|
||
|
* @return the remote device's {@link UwbAddress}
|
||
|
*/
|
||
|
@NonNull
|
||
|
public UwbAddress getRemoteDeviceAddress() {
|
||
|
return mRemoteDeviceAddress;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
@IntDef(value = {
|
||
|
RANGING_STATUS_SUCCESS,
|
||
|
RANGING_STATUS_FAILURE_OUT_OF_RANGE,
|
||
|
RANGING_STATUS_FAILURE_UNKNOWN_ERROR})
|
||
|
public @interface Status {}
|
||
|
|
||
|
/**
|
||
|
* Ranging attempt was successful for this device
|
||
|
*/
|
||
|
public static final int RANGING_STATUS_SUCCESS = 0;
|
||
|
|
||
|
/**
|
||
|
* Ranging failed for this device because it is out of range
|
||
|
*/
|
||
|
public static final int RANGING_STATUS_FAILURE_OUT_OF_RANGE = 1;
|
||
|
|
||
|
/**
|
||
|
* Ranging failed for this device because of unknown error
|
||
|
*/
|
||
|
public static final int RANGING_STATUS_FAILURE_UNKNOWN_ERROR = -1;
|
||
|
|
||
|
/**
|
||
|
* Get the status of this ranging measurement
|
||
|
*
|
||
|
* <p>Possible values are
|
||
|
* {@link #RANGING_STATUS_SUCCESS},
|
||
|
* {@link #RANGING_STATUS_FAILURE_OUT_OF_RANGE},
|
||
|
* {@link #RANGING_STATUS_FAILURE_UNKNOWN_ERROR}.
|
||
|
*
|
||
|
* @return the status of the ranging measurement
|
||
|
*/
|
||
|
@Status
|
||
|
public int getStatus() {
|
||
|
return mStatus;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Timestamp of this ranging measurement in time since boot nanos in the same namespace as
|
||
|
* {@link SystemClock#elapsedRealtimeNanos()}
|
||
|
*
|
||
|
* @return timestamp of ranging measurement in nanoseconds
|
||
|
*/
|
||
|
@SuppressLint("MethodNameUnits")
|
||
|
public long getElapsedRealtimeNanos() {
|
||
|
return mElapsedRealtimeNanos;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the distance measurement
|
||
|
*
|
||
|
* @return a {@link DistanceMeasurement} or null if {@link #getStatus()} !=
|
||
|
* {@link #RANGING_STATUS_SUCCESS}
|
||
|
*/
|
||
|
@Nullable
|
||
|
public DistanceMeasurement getDistanceMeasurement() {
|
||
|
return mDistanceMeasurement;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the angle of arrival measurement
|
||
|
*
|
||
|
* @return an {@link AngleOfArrivalMeasurement} or null if {@link #getStatus()} !=
|
||
|
* {@link #RANGING_STATUS_SUCCESS}
|
||
|
*/
|
||
|
@Nullable
|
||
|
public AngleOfArrivalMeasurement getAngleOfArrivalMeasurement() {
|
||
|
return mAngleOfArrivalMeasurement;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the angle of arrival measurement at the destination.
|
||
|
*
|
||
|
* @return an {@link AngleOfArrivalMeasurement} or null if {@link #getStatus()} !=
|
||
|
* {@link #RANGING_STATUS_SUCCESS}
|
||
|
*/
|
||
|
@Nullable
|
||
|
public AngleOfArrivalMeasurement getDestinationAngleOfArrivalMeasurement() {
|
||
|
return mDestinationAngleOfArrivalMeasurement;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
@IntDef(value = {
|
||
|
LOS,
|
||
|
NLOS,
|
||
|
LOS_UNDETERMINED})
|
||
|
public @interface LineOfSight {}
|
||
|
|
||
|
/**
|
||
|
* If measurement was in line of sight.
|
||
|
*/
|
||
|
public static final int LOS = 0;
|
||
|
|
||
|
/**
|
||
|
* If measurement was not in line of sight.
|
||
|
*/
|
||
|
public static final int NLOS = 1;
|
||
|
|
||
|
/**
|
||
|
* Unable to determine whether the measurement was in line of sight or not.
|
||
|
*/
|
||
|
public static final int LOS_UNDETERMINED = 0xFF;
|
||
|
|
||
|
/**
|
||
|
* Get whether the measurement was in Line of sight or non-line of sight.
|
||
|
*
|
||
|
* @return whether the measurement was in line of sight or not
|
||
|
*/
|
||
|
public @LineOfSight int getLineOfSight() {
|
||
|
return mLineOfSight;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the measured RSSI in dBm
|
||
|
*/
|
||
|
public @IntRange(from = RSSI_UNKNOWN, to = RSSI_MAX) int getRssiDbm() {
|
||
|
return mRssiDbm;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
@IntDef(value = {
|
||
|
MEASUREMENT_FOCUS_NONE,
|
||
|
MEASUREMENT_FOCUS_RANGE,
|
||
|
MEASUREMENT_FOCUS_ANGLE_OF_ARRIVAL_AZIMUTH,
|
||
|
MEASUREMENT_FOCUS_ANGLE_OF_ARRIVAL_ELEVATION})
|
||
|
public @interface MeasurementFocus {}
|
||
|
|
||
|
/**
|
||
|
* Ranging measurement was done with no particular focus in terms of antenna selection.
|
||
|
*/
|
||
|
public static final int MEASUREMENT_FOCUS_NONE = 0;
|
||
|
|
||
|
/**
|
||
|
* Ranging measurement was done with a focus on range calculation in terms of antenna
|
||
|
* selection.
|
||
|
*/
|
||
|
public static final int MEASUREMENT_FOCUS_RANGE = 1;
|
||
|
|
||
|
/**
|
||
|
* Ranging measurement was done with a focus on Angle of arrival azimuth calculation in terms of
|
||
|
* antenna selection.
|
||
|
*/
|
||
|
public static final int MEASUREMENT_FOCUS_ANGLE_OF_ARRIVAL_AZIMUTH = 2;
|
||
|
|
||
|
/**
|
||
|
* Ranging measurement was done with a focus on Angle of arrival elevation calculation in terms
|
||
|
* of antenna selection.
|
||
|
*/
|
||
|
public static final int MEASUREMENT_FOCUS_ANGLE_OF_ARRIVAL_ELEVATION = 3;
|
||
|
|
||
|
/**
|
||
|
* Gets the measurement focus in terms of antenna used for this measurement.
|
||
|
*
|
||
|
* @return focus of this measurement.
|
||
|
*/
|
||
|
public @MeasurementFocus int getMeasurementFocus() {
|
||
|
return mMeasurementFocus;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets ranging measurement metadata passed by vendor
|
||
|
*
|
||
|
* @return vendor data for ranging measurement
|
||
|
*/
|
||
|
@NonNull
|
||
|
public PersistableBundle getRangingMeasurementMetadata() {
|
||
|
return mRangingMeasurementMetadata;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
@Override
|
||
|
public boolean equals(@Nullable Object obj) {
|
||
|
if (this == obj) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (obj instanceof RangingMeasurement) {
|
||
|
RangingMeasurement other = (RangingMeasurement) obj;
|
||
|
return Objects.equals(mRemoteDeviceAddress, other.getRemoteDeviceAddress())
|
||
|
&& mStatus == other.getStatus()
|
||
|
&& mElapsedRealtimeNanos == other.getElapsedRealtimeNanos()
|
||
|
&& Objects.equals(mDistanceMeasurement, other.getDistanceMeasurement())
|
||
|
&& Objects.equals(
|
||
|
mAngleOfArrivalMeasurement, other.getAngleOfArrivalMeasurement())
|
||
|
&& Objects.equals(
|
||
|
mDestinationAngleOfArrivalMeasurement,
|
||
|
other.getDestinationAngleOfArrivalMeasurement())
|
||
|
&& mLineOfSight == other.getLineOfSight()
|
||
|
&& mMeasurementFocus == other.getMeasurementFocus()
|
||
|
&& mRssiDbm == other.getRssiDbm()
|
||
|
&& PersistableBundleUtils.isEqual(mRangingMeasurementMetadata,
|
||
|
other.mRangingMeasurementMetadata);
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
return Objects.hash(mRemoteDeviceAddress, mStatus, mElapsedRealtimeNanos,
|
||
|
mDistanceMeasurement, mAngleOfArrivalMeasurement,
|
||
|
mDestinationAngleOfArrivalMeasurement, mLineOfSight, mMeasurementFocus, mRssiDbm,
|
||
|
PersistableBundleUtils.getHashCode(mRangingMeasurementMetadata));
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int describeContents() {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||
|
dest.writeParcelable(mRemoteDeviceAddress, flags);
|
||
|
dest.writeInt(mStatus);
|
||
|
dest.writeLong(mElapsedRealtimeNanos);
|
||
|
dest.writeParcelable(mDistanceMeasurement, flags);
|
||
|
dest.writeParcelable(mAngleOfArrivalMeasurement, flags);
|
||
|
dest.writeParcelable(mDestinationAngleOfArrivalMeasurement, flags);
|
||
|
dest.writeInt(mLineOfSight);
|
||
|
dest.writeInt(mMeasurementFocus);
|
||
|
dest.writeInt(mRssiDbm);
|
||
|
dest.writePersistableBundle(mRangingMeasurementMetadata);
|
||
|
}
|
||
|
|
||
|
public static final @android.annotation.NonNull Creator<RangingMeasurement> CREATOR =
|
||
|
new Creator<RangingMeasurement>() {
|
||
|
@Override
|
||
|
public RangingMeasurement createFromParcel(Parcel in) {
|
||
|
Builder builder = new Builder();
|
||
|
builder.setRemoteDeviceAddress(
|
||
|
in.readParcelable(UwbAddress.class.getClassLoader()));
|
||
|
builder.setStatus(in.readInt());
|
||
|
builder.setElapsedRealtimeNanos(in.readLong());
|
||
|
builder.setDistanceMeasurement(
|
||
|
in.readParcelable(DistanceMeasurement.class.getClassLoader()));
|
||
|
builder.setAngleOfArrivalMeasurement(
|
||
|
in.readParcelable(AngleOfArrivalMeasurement.class.getClassLoader()));
|
||
|
builder.setDestinationAngleOfArrivalMeasurement(
|
||
|
in.readParcelable(AngleOfArrivalMeasurement.class.getClassLoader()));
|
||
|
builder.setLineOfSight(in.readInt());
|
||
|
builder.setMeasurementFocus(in.readInt());
|
||
|
builder.setRssiDbm(in.readInt());
|
||
|
PersistableBundle metadata =
|
||
|
in.readPersistableBundle(getClass().getClassLoader());
|
||
|
if (metadata != null) builder.setRangingMeasurementMetadata(metadata);
|
||
|
return builder.build();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public RangingMeasurement[] newArray(int size) {
|
||
|
return new RangingMeasurement[size];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/** @hide **/
|
||
|
@Override
|
||
|
public String toString() {
|
||
|
return "RangingMeasurement["
|
||
|
+ "remote device address:" + mRemoteDeviceAddress
|
||
|
+ ", distance measurement: " + mDistanceMeasurement
|
||
|
+ ", aoa measurement: " + mAngleOfArrivalMeasurement
|
||
|
+ ", dest aoa measurement: " + mDestinationAngleOfArrivalMeasurement
|
||
|
+ ", lineOfSight: " + mLineOfSight
|
||
|
+ ", measurementFocus: " + mMeasurementFocus
|
||
|
+ ", rssiDbm: " + mRssiDbm
|
||
|
+ ", ranging measurement metadata: " + mRangingMeasurementMetadata
|
||
|
+ ", elapsed real time nanos: " + mElapsedRealtimeNanos
|
||
|
+ ", status: " + mStatus
|
||
|
+ "]";
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Builder for a {@link RangingMeasurement} object.
|
||
|
*/
|
||
|
public static final class Builder {
|
||
|
private UwbAddress mRemoteDeviceAddress = null;
|
||
|
private @Status int mStatus = RANGING_STATUS_FAILURE_UNKNOWN_ERROR;
|
||
|
private long mElapsedRealtimeNanos = -1L;
|
||
|
private DistanceMeasurement mDistanceMeasurement = null;
|
||
|
private AngleOfArrivalMeasurement mAngleOfArrivalMeasurement = null;
|
||
|
private AngleOfArrivalMeasurement mDestinationAngleOfArrivalMeasurement = null;
|
||
|
private @LineOfSight int mLineOfSight = LOS_UNDETERMINED;
|
||
|
private @MeasurementFocus int mMeasurementFocus = MEASUREMENT_FOCUS_NONE;
|
||
|
private int mRssiDbm = RSSI_UNKNOWN;
|
||
|
private PersistableBundle mRangingMeasurementMetadata = null;
|
||
|
|
||
|
/**
|
||
|
* Set the remote device address that this measurement is for
|
||
|
*
|
||
|
* @param remoteDeviceAddress remote device's address
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setRemoteDeviceAddress(@NonNull UwbAddress remoteDeviceAddress) {
|
||
|
mRemoteDeviceAddress = remoteDeviceAddress;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the status of ranging measurement
|
||
|
*
|
||
|
* @param status the status of the ranging measurement
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setStatus(@Status int status) {
|
||
|
mStatus = status;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the elapsed realtime in nanoseconds when the ranging measurement occurred
|
||
|
*
|
||
|
* @param elapsedRealtimeNanos time the ranging measurement occurred
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setElapsedRealtimeNanos(long elapsedRealtimeNanos) {
|
||
|
if (elapsedRealtimeNanos < 0) {
|
||
|
throw new IllegalArgumentException("elapsedRealtimeNanos must be >= 0");
|
||
|
}
|
||
|
mElapsedRealtimeNanos = elapsedRealtimeNanos;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the {@link DistanceMeasurement}
|
||
|
*
|
||
|
* @param distanceMeasurement the distance measurement for this ranging measurement
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setDistanceMeasurement(@NonNull DistanceMeasurement distanceMeasurement) {
|
||
|
mDistanceMeasurement = distanceMeasurement;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the {@link AngleOfArrivalMeasurement}
|
||
|
*
|
||
|
* @param angleOfArrivalMeasurement the angle of arrival measurement for this ranging
|
||
|
* measurement
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setAngleOfArrivalMeasurement(
|
||
|
@NonNull AngleOfArrivalMeasurement angleOfArrivalMeasurement) {
|
||
|
mAngleOfArrivalMeasurement = angleOfArrivalMeasurement;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the {@link AngleOfArrivalMeasurement} at the destination.
|
||
|
*
|
||
|
* @param angleOfArrivalMeasurement the angle of arrival measurement for this ranging
|
||
|
* measurement
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setDestinationAngleOfArrivalMeasurement(
|
||
|
@NonNull AngleOfArrivalMeasurement angleOfArrivalMeasurement) {
|
||
|
mDestinationAngleOfArrivalMeasurement = angleOfArrivalMeasurement;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set whether the measurement was in Line of sight or non-line of sight.
|
||
|
*
|
||
|
* @param lineOfSight whether the measurement was in line of sight or not
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setLineOfSight(@LineOfSight int lineOfSight) {
|
||
|
mLineOfSight = lineOfSight;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the measurement focus in terms of antenna used for this measurement.
|
||
|
*
|
||
|
* @param measurementFocus focus of this measurement.
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setMeasurementFocus(@MeasurementFocus int measurementFocus) {
|
||
|
mMeasurementFocus = measurementFocus;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the RSSI in dBm
|
||
|
*
|
||
|
* @param rssiDbm the measured RSSI in dBm
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setRssiDbm(@IntRange(from = RSSI_UNKNOWN, to = RSSI_MAX) int rssiDbm) {
|
||
|
if (rssiDbm != RSSI_UNKNOWN && (rssiDbm < RSSI_MIN || rssiDbm > RSSI_MAX)) {
|
||
|
throw new IllegalArgumentException("Invalid rssiDbm: " + rssiDbm);
|
||
|
}
|
||
|
mRssiDbm = rssiDbm;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set Ranging measurement metadata
|
||
|
*
|
||
|
* @param rangingMeasurementMetadata vendor data per ranging measurement
|
||
|
*
|
||
|
* @throws IllegalStateException if rangingMeasurementMetadata is null
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setRangingMeasurementMetadata(@NonNull
|
||
|
PersistableBundle rangingMeasurementMetadata) {
|
||
|
if (rangingMeasurementMetadata == null) {
|
||
|
throw new IllegalStateException("Expected non-null rangingMeasurementMetadata");
|
||
|
}
|
||
|
mRangingMeasurementMetadata = rangingMeasurementMetadata;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Build the {@link RangingMeasurement} object
|
||
|
*
|
||
|
* @throws IllegalStateException if a distance or angle of arrival measurement is provided
|
||
|
* but the measurement was not successful, if the
|
||
|
* elapsedRealtimeNanos of the measurement is invalid, or
|
||
|
* if no remote device address is set
|
||
|
*/
|
||
|
@NonNull
|
||
|
public RangingMeasurement build() {
|
||
|
if (mStatus != RANGING_STATUS_SUCCESS) {
|
||
|
if (mDistanceMeasurement != null) {
|
||
|
throw new IllegalStateException(
|
||
|
"Distance Measurement must be null if ranging is not successful");
|
||
|
}
|
||
|
|
||
|
if (mAngleOfArrivalMeasurement != null) {
|
||
|
throw new IllegalStateException(
|
||
|
"Angle of Arrival must be null if ranging is not successful");
|
||
|
}
|
||
|
|
||
|
// Destination AOA is optional according to the spec.
|
||
|
}
|
||
|
|
||
|
if (mRemoteDeviceAddress == null) {
|
||
|
throw new IllegalStateException("No remote device address was set");
|
||
|
}
|
||
|
|
||
|
if (mElapsedRealtimeNanos < 0) {
|
||
|
throw new IllegalStateException(
|
||
|
"elapsedRealtimeNanos must be >=0: " + mElapsedRealtimeNanos);
|
||
|
}
|
||
|
|
||
|
return new RangingMeasurement(mRemoteDeviceAddress, mStatus, mElapsedRealtimeNanos,
|
||
|
mDistanceMeasurement, mAngleOfArrivalMeasurement,
|
||
|
mDestinationAngleOfArrivalMeasurement, mLineOfSight, mMeasurementFocus,
|
||
|
mRssiDbm, mRangingMeasurementMetadata);
|
||
|
}
|
||
|
}
|
||
|
}
|