/* * Copyright 2022 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.FlaggedApi; import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import com.android.bluetooth.flags.Flags; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Result of distance measurement. * * @hide */ @SystemApi public final class DistanceMeasurementResult implements Parcelable { /** * Normalized Attack Detector Metric. See Channel Sounding CR_PR, 3.13.24 for details. * *
Specification: https://www.bluetooth.com/specifications/specs/channel-sounding-cr-pr/ * * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef( value = { NADM_ATTACK_IS_EXTREMELY_UNLIKELY, NADM_ATTACK_IS_VERY_UNLIKELY, NADM_ATTACK_IS_UNLIKELY, NADM_ATTACK_IS_POSSIBLE, NADM_ATTACK_IS_LIKELY, NADM_ATTACK_IS_VERY_LIKELY, NADM_ATTACK_IS_EXTREMELY_LIKELY, NADM_UNKNOWN }) @interface Nadm {} /** * Attack is extremely unlikely. * * @hide */ @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING) @SystemApi public static final int NADM_ATTACK_IS_EXTREMELY_UNLIKELY = 0; /** * Attack is very unlikely. * * @hide */ @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING) @SystemApi public static final int NADM_ATTACK_IS_VERY_UNLIKELY = 1; /** * Attack is unlikely. * * @hide */ @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING) @SystemApi public static final int NADM_ATTACK_IS_UNLIKELY = 2; /** * Attack is possible. * * @hide */ @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING) @SystemApi public static final int NADM_ATTACK_IS_POSSIBLE = 3; /** * Attack is likely. * * @hide */ @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING) @SystemApi public static final int NADM_ATTACK_IS_LIKELY = 4; /** * Attack is very likely. * * @hide */ @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING) @SystemApi public static final int NADM_ATTACK_IS_VERY_LIKELY = 5; /** * Attack is extremely likely. * * @hide */ @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING) @SystemApi public static final int NADM_ATTACK_IS_EXTREMELY_LIKELY = 6; /** * Unknown NADM, if a device is unable to determine a NADM value, then it shall report this. * * @hide */ @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING) @SystemApi public static final int NADM_UNKNOWN = 0xFF; private final double mMeters; private final double mErrorMeters; private final double mAzimuthAngle; private final double mErrorAzimuthAngle; private final double mAltitudeAngle; private final double mErrorAltitudeAngle; private final double mDelaySpreadMeters; private final double mConfidenceLevel; private final int mDetectedAttackLevel; private final double mVelocityMetersPerSecond; private DistanceMeasurementResult( double meters, double errorMeters, double azimuthAngle, double errorAzimuthAngle, double altitudeAngle, double errorAltitudeAngle, double delaySpreadMeters, double confidenceLevel, @Nadm int detectedAttackLevel, double velocityMetersPerSecond) { mMeters = meters; mErrorMeters = errorMeters; mAzimuthAngle = azimuthAngle; mErrorAzimuthAngle = errorAzimuthAngle; mAltitudeAngle = altitudeAngle; mErrorAltitudeAngle = errorAltitudeAngle; mDelaySpreadMeters = delaySpreadMeters; mConfidenceLevel = confidenceLevel; mDetectedAttackLevel = detectedAttackLevel; mVelocityMetersPerSecond = velocityMetersPerSecond; } /** * Distance measurement in meters. * * @return distance in meters * @hide */ @SystemApi public double getResultMeters() { return mMeters; } /** * Error of distance measurement in meters. * *
Must be positive. * * @return error of distance measurement in meters * @hide */ @SystemApi @FloatRange(from = 0.0) public double getErrorMeters() { return mErrorMeters; } /** * Azimuth Angle measurement in degrees. * *
Azimuth of remote device in horizontal coordinate system, this measured from azimuth north * and increasing eastward. When the remote device in azimuth north, this angle is 0, whe the * remote device in azimuth south, this angle is 180. * *
See: Horizontal * coordinate systemfor the details * *
On an Android device, azimuth north is defined as the angle perpendicular away from the * back of the device when holding it in portrait mode upright. * *
The Azimuth north is defined as the direction in which the top edge of the device is * facing when it is placed flat. * * @return azimuth angle in degrees or Double.NaN if not available * @hide */ @SystemApi @FloatRange(from = 0.0, to = 360.0) public double getAzimuthAngle() { return mAzimuthAngle; } /** * Error of azimuth angle measurement in degrees. * *
Must be a positive value. * * @return azimuth angle measurement error in degrees or Double.NaN if not available * @hide */ @SystemApi public double getErrorAzimuthAngle() { return mErrorAzimuthAngle; } /** * Altitude Angle measurement in degrees. * *
Altitude of remote device in horizontal coordinate system, this is the angle between the * remote device and the top edge of local device. When local device is placed flat, the angle * of the zenith is 90, the angle of the nadir is -90. * *
See: https://en.wikipedia.org/wiki/Horizontal_coordinate_system * * @return altitude angle in degrees or Double.NaN if not available * @hide */ @SystemApi @FloatRange(from = -90.0, to = 90.0) public double getAltitudeAngle() { return mAltitudeAngle; } /** * Error of altitude angle measurement in degrees. * *
Must be a positive value.
*
* @return altitude angle measurement error in degrees or Double.NaN if not available
* @hide
*/
@SystemApi
public double getErrorAltitudeAngle() {
return mErrorAltitudeAngle;
}
/**
* Get estimated delay spread in meters of the measured channel. This is a measure of multipath
* richness of the channel.
*
* @return delay spread in meters in degrees or Double.NaN if not available
* @hide
*/
@FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING)
@SystemApi
public double getDelaySpreadMeters() {
return mDelaySpreadMeters;
}
/**
* Get a normalized value from 0.0 (low confidence) to 1.0 (high confidence) representing the
* confidence of estimated distance.
*
* @return confidence of estimated distance or Double.NaN if not available
* @hide
*/
@FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING)
@SystemApi
@FloatRange(from = 0.0, to = 1.0)
public double getConfidenceLevel() {
return mConfidenceLevel;
}
/**
* Get a value that represents the chance of being attacked for the measurement.
*
* @return Nadm that represents the chance of being attacked for the measurement.
* @hide
*/
@FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING)
@SystemApi
@Nadm
public int getDetectedAttackLevel() {
return mDetectedAttackLevel;
}
/**
* Get estimated velocity, in the direction of line between two devices, of the moving object in
* meters/sec.
*
* @return Estimated velocity, in the direction of line between two devices, of the moving
* object in meters/sec.
* @hide
*/
@FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING)
@SystemApi
public double getVelocityMetersPerSecond() {
return mVelocityMetersPerSecond;
}
/**
* {@inheritDoc}
*
* @hide
*/
@Override
public int describeContents() {
return 0;
}
/**
* {@inheritDoc}
*
* @hide
*/
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeDouble(mMeters);
out.writeDouble(mErrorMeters);
out.writeDouble(mAzimuthAngle);
out.writeDouble(mErrorAzimuthAngle);
out.writeDouble(mAltitudeAngle);
out.writeDouble(mErrorAltitudeAngle);
out.writeDouble(mDelaySpreadMeters);
out.writeDouble(mConfidenceLevel);
out.writeInt(mDetectedAttackLevel);
out.writeDouble(mVelocityMetersPerSecond);
}
/**
* @hide *
*/
@Override
public String toString() {
return "DistanceMeasurement["
+ "meters: "
+ mMeters
+ ", errorMeters: "
+ mErrorMeters
+ ", azimuthAngle: "
+ mAzimuthAngle
+ ", errorAzimuthAngle: "
+ mErrorAzimuthAngle
+ ", altitudeAngle: "
+ mAltitudeAngle
+ ", errorAltitudeAngle: "
+ mErrorAltitudeAngle
+ ", delaySpreadMeters: "
+ mDelaySpreadMeters
+ ", confidenceLevel: "
+ mConfidenceLevel
+ ", detectedAttackLevel: "
+ mDetectedAttackLevel
+ ", velocityMetersPerSecond: "
+ mVelocityMetersPerSecond
+ "]";
}
/** A {@link Parcelable.Creator} to create {@link DistanceMeasurementResult} from parcel. */
public static final @NonNull Parcelable.Creator