/* * Copyright (C) 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.location; import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_ATTENUATION; import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH; import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH_UNC; import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_REFLECTING_PLANE; import android.annotation.FloatRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import com.android.internal.util.Preconditions; import java.util.Objects; /** * Contains the info of an excess path signal caused by reflection * * @hide */ @SystemApi public final class GnssExcessPathInfo implements Parcelable { private static final int HAS_EXCESS_PATH_LENGTH_MASK = EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH; private static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK = EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH_UNC; private static final int HAS_REFLECTING_PLANE_MASK = EXCESS_PATH_INFO_HAS_REFLECTING_PLANE; private static final int HAS_ATTENUATION_MASK = EXCESS_PATH_INFO_HAS_ATTENUATION; /* A bitmask of fields present in this object (see HAS_* constants defined above) */ private final int mFlags; private final float mExcessPathLengthMeters; private final float mExcessPathLengthUncertaintyMeters; @Nullable private final GnssReflectingPlane mReflectingPlane; private final float mAttenuationDb; private GnssExcessPathInfo( int flags, float excessPathLengthMeters, float excessPathLengthUncertaintyMeters, @Nullable GnssReflectingPlane reflectingPlane, float attenuationDb) { mFlags = flags; mExcessPathLengthMeters = excessPathLengthMeters; mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters; mReflectingPlane = reflectingPlane; mAttenuationDb = attenuationDb; } /** * Gets a bitmask of fields present in this object. * *
This API exists for JNI since it is easier for JNI to get one integer flag than looking up * several has* methods. * @hide */ public int getFlags() { return mFlags; } /** Returns {@code true} if {@link #getExcessPathLengthMeters()} is valid. */ public boolean hasExcessPathLength() { return (mFlags & HAS_EXCESS_PATH_LENGTH_MASK) != 0; } /** * Returns the excess path length to be subtracted from pseudorange before using it in * calculating location. * *
{@link #hasExcessPathLength()} must be true when calling this method. Otherwise, an * {@link UnsupportedOperationException} will be thrown. */ @FloatRange(from = 0.0f) public float getExcessPathLengthMeters() { if (!hasExcessPathLength()) { throw new UnsupportedOperationException( "getExcessPathLengthMeters() is not supported when hasExcessPathLength() is " + "false"); } return mExcessPathLengthMeters; } /** Returns {@code true} if {@link #getExcessPathLengthUncertaintyMeters()} is valid. */ public boolean hasExcessPathLengthUncertainty() { return (mFlags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0; } /** * Returns the error estimate (1-sigma) for the excess path length estimate. * *
{@link #hasExcessPathLengthUncertainty()} must be true when calling this method. * Otherwise, an {@link UnsupportedOperationException} will be thrown. */ @FloatRange(from = 0.0f) public float getExcessPathLengthUncertaintyMeters() { if (!hasExcessPathLengthUncertainty()) { throw new UnsupportedOperationException( "getExcessPathLengthUncertaintyMeters() is not supported when " + "hasExcessPathLengthUncertainty() is false"); } return mExcessPathLengthUncertaintyMeters; } /** * Returns {@code true} if {@link #getReflectingPlane()} is valid. * *
Returns false if the satellite signal goes through multiple reflections or if reflection * plane serving is not supported. */ public boolean hasReflectingPlane() { return (mFlags & HAS_REFLECTING_PLANE_MASK) != 0; } /** * Returns the reflecting plane characteristics at which the signal has bounced. * *
{@link #hasReflectingPlane()} must be true when calling this method. Otherwise, an * {@link UnsupportedOperationException} will be thrown. */ @NonNull public GnssReflectingPlane getReflectingPlane() { if (!hasReflectingPlane()) { throw new UnsupportedOperationException( "getReflectingPlane() is not supported when hasReflectingPlane() is false"); } return mReflectingPlane; } /** Returns {@code true} if {@link #getAttenuationDb()} is valid. */ public boolean hasAttenuation() { return (mFlags & HAS_ATTENUATION_MASK) != 0; } /** * Returns the expected reduction of signal strength of this path in non-negative dB. * *
{@link #hasAttenuation()} must be true when calling this method. Otherwise, an
* {@link UnsupportedOperationException} will be thrown.
*/
@FloatRange(from = 0.0f)
public float getAttenuationDb() {
if (!hasAttenuation()) {
throw new UnsupportedOperationException(
"getAttenuationDb() is not supported when hasAttenuation() is false");
}
return mAttenuationDb;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel parcel, int parcelFlags) {
parcel.writeInt(mFlags);
if (hasExcessPathLength()) {
parcel.writeFloat(mExcessPathLengthMeters);
}
if (hasExcessPathLengthUncertainty()) {
parcel.writeFloat(mExcessPathLengthUncertaintyMeters);
}
if (hasReflectingPlane()) {
mReflectingPlane.writeToParcel(parcel, parcelFlags);
}
if (hasAttenuation()) {
parcel.writeFloat(mAttenuationDb);
}
}
public static final @NonNull Creator This is to negate {@link #setExcessPathLengthMeters} call.
*/
@NonNull
public Builder clearExcessPathLengthMeters() {
mExcessPathLengthMeters = 0;
mFlags &= ~HAS_EXCESS_PATH_LENGTH_MASK;
return this;
}
/** Sets the error estimate (1-sigma) for the excess path length estimate */
@NonNull
public Builder setExcessPathLengthUncertaintyMeters(
@FloatRange(from = 0.0f) float excessPathLengthUncertaintyMeters) {
Preconditions.checkArgumentInRange(excessPathLengthUncertaintyMeters, 0,
Float.MAX_VALUE, "excessPathLengthUncertaintyMeters");
mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
mFlags |= HAS_EXCESS_PATH_LENGTH_UNC_MASK;
return this;
}
/**
* Clears the error estimate (1-sigma) for the excess path length estimate
*
* This is to negate {@link #setExcessPathLengthUncertaintyMeters} call.
*/
@NonNull
public Builder clearExcessPathLengthUncertaintyMeters() {
mExcessPathLengthUncertaintyMeters = 0;
mFlags &= ~HAS_EXCESS_PATH_LENGTH_UNC_MASK;
return this;
}
/** Sets the reflecting plane information */
@NonNull
public Builder setReflectingPlane(@Nullable GnssReflectingPlane reflectingPlane) {
mReflectingPlane = reflectingPlane;
if (reflectingPlane != null) {
mFlags |= HAS_REFLECTING_PLANE_MASK;
} else {
mFlags &= ~HAS_REFLECTING_PLANE_MASK;
}
return this;
}
/**
* Sets the attenuation value in dB.
*/
@NonNull
public Builder setAttenuationDb(@FloatRange(from = 0.0f) float attenuationDb) {
Preconditions.checkArgumentInRange(attenuationDb, 0, Float.MAX_VALUE,
"attenuationDb");
mAttenuationDb = attenuationDb;
mFlags |= HAS_ATTENUATION_MASK;
return this;
}
/**
* Clears the attenuation value in dB.
*
* This is to negate {@link #setAttenuationDb(float)} call.
*/
@NonNull
public Builder clearAttenuationDb() {
mAttenuationDb = 0;
mFlags &= ~HAS_ATTENUATION_MASK;
return this;
}
/** Builds a {@link GnssExcessPathInfo} instance as specified by this builder. */
@NonNull
public GnssExcessPathInfo build() {
return new GnssExcessPathInfo(
mFlags,
mExcessPathLengthMeters,
mExcessPathLengthUncertaintyMeters,
mReflectingPlane,
mAttenuationDb);
}
}
}