1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.location; 18 19 import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_COMBINED_ATTENUATION; 20 import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH; 21 import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH_UNC; 22 import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY; 23 24 import android.annotation.FloatRange; 25 import android.annotation.IntRange; 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.annotation.SystemApi; 29 import android.os.Parcel; 30 import android.os.Parcelable; 31 32 import com.android.internal.util.Preconditions; 33 34 import java.util.ArrayList; 35 import java.util.List; 36 import java.util.Objects; 37 38 /** 39 * A container with measurement corrections for a single visible satellite 40 * 41 * @hide 42 */ 43 @SystemApi 44 public final class GnssSingleSatCorrection implements Parcelable { 45 46 private static final int HAS_PROB_SAT_IS_LOS_MASK = 47 SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY; 48 private static final int HAS_COMBINED_EXCESS_PATH_LENGTH_MASK = 49 SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH; 50 private static final int HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK = 51 SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH_UNC; 52 private static final int HAS_COMBINED_ATTENUATION_MASK = 53 SINGLE_SAT_CORRECTION_HAS_COMBINED_ATTENUATION; 54 55 /* A bitmask of fields present in this object (see HAS_* constants defined above). */ 56 private final int mSingleSatCorrectionFlags; 57 58 private final int mConstellationType; 59 private final int mSatId; 60 private final float mCarrierFrequencyHz; 61 private final float mProbSatIsLos; 62 private final float mCombinedExcessPathLengthMeters; 63 private final float mCombinedExcessPathLengthUncertaintyMeters; 64 private final float mCombinedAttenuationDb; 65 66 @NonNull 67 private final List<GnssExcessPathInfo> mGnssExcessPathInfoList; 68 GnssSingleSatCorrection(int singleSatCorrectionFlags, int constellationType, int satId, float carrierFrequencyHz, float probSatIsLos, float excessPathLengthMeters, float excessPathLengthUncertaintyMeters, float combinedAttenuationDb, @NonNull List<GnssExcessPathInfo> gnssExcessPathInfoList)69 private GnssSingleSatCorrection(int singleSatCorrectionFlags, int constellationType, int satId, 70 float carrierFrequencyHz, float probSatIsLos, float excessPathLengthMeters, 71 float excessPathLengthUncertaintyMeters, 72 float combinedAttenuationDb, 73 @NonNull List<GnssExcessPathInfo> gnssExcessPathInfoList) { 74 mSingleSatCorrectionFlags = singleSatCorrectionFlags; 75 mConstellationType = constellationType; 76 mSatId = satId; 77 mCarrierFrequencyHz = carrierFrequencyHz; 78 mProbSatIsLos = probSatIsLos; 79 mCombinedExcessPathLengthMeters = excessPathLengthMeters; 80 mCombinedExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters; 81 mCombinedAttenuationDb = combinedAttenuationDb; 82 mGnssExcessPathInfoList = gnssExcessPathInfoList; 83 } 84 85 /** 86 * Gets a bitmask of fields present in this object. 87 * 88 * @hide 89 */ getSingleSatelliteCorrectionFlags()90 public int getSingleSatelliteCorrectionFlags() { 91 return mSingleSatCorrectionFlags; 92 } 93 94 /** 95 * Gets the constellation type. 96 * 97 * <p>The return value is one of those constants with {@code CONSTELLATION_} prefix in {@link 98 * GnssStatus}. 99 */ 100 @GnssStatus.ConstellationType getConstellationType()101 public int getConstellationType() { 102 return mConstellationType; 103 } 104 105 /** 106 * Gets the satellite ID. 107 * 108 * <p>Interpretation depends on {@link #getConstellationType()}. See {@link 109 * GnssStatus#getSvid(int)}. 110 */ 111 @IntRange(from = 0) getSatelliteId()112 public int getSatelliteId() { 113 return mSatId; 114 } 115 116 /** 117 * Gets the carrier frequency of the tracked signal. 118 * 119 * <p>For example it can be the GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz, 120 * L5 = 1176.45 MHz, varying GLO channels, etc. 121 * 122 * <p>For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two correction 123 * objects will be reported for this same satellite, in one of the correction objects, all the 124 * values related to L1 will be filled, and in the other all of the values related to L5 will be 125 * filled. 126 * 127 * @return the carrier frequency of the signal tracked in Hz. 128 */ 129 @FloatRange(from = 0.0f, fromInclusive = false) getCarrierFrequencyHz()130 public float getCarrierFrequencyHz() { 131 return mCarrierFrequencyHz; 132 } 133 134 /** 135 * Returns the probability that the satellite is in line-of-sight condition at the given 136 * location. 137 */ 138 @FloatRange(from = 0.0f, to = 1.0f) getProbabilityLineOfSight()139 public float getProbabilityLineOfSight() { 140 return mProbSatIsLos; 141 } 142 143 /** 144 * Returns the combined excess path length to be subtracted from pseudorange before using it in 145 * calculating location. 146 */ 147 @FloatRange(from = 0.0f) getExcessPathLengthMeters()148 public float getExcessPathLengthMeters() { 149 return mCombinedExcessPathLengthMeters; 150 } 151 152 /** Returns the error estimate (1-sigma) for the combined excess path length estimate. */ 153 @FloatRange(from = 0.0f) getExcessPathLengthUncertaintyMeters()154 public float getExcessPathLengthUncertaintyMeters() { 155 return mCombinedExcessPathLengthUncertaintyMeters; 156 } 157 158 /** 159 * Returns the combined expected reduction of signal strength for this satellite in 160 * non-negative dB. 161 */ 162 @FloatRange(from = 0.0f) getCombinedAttenuationDb()163 public float getCombinedAttenuationDb() { 164 return mCombinedAttenuationDb; 165 } 166 167 /** 168 * Returns the reflecting plane characteristics at which the signal has bounced. 169 * 170 * @deprecated Combined excess path does not have a reflecting plane. 171 */ 172 @Nullable 173 @Deprecated getReflectingPlane()174 public GnssReflectingPlane getReflectingPlane() { 175 return null; 176 } 177 178 /** 179 * Returns the list of {@link GnssExcessPathInfo} associated with this satellite signal. 180 */ 181 @NonNull getGnssExcessPathInfoList()182 public List<GnssExcessPathInfo> getGnssExcessPathInfoList() { 183 return mGnssExcessPathInfoList; 184 } 185 186 /** Returns {@code true} if {@link #getProbabilityLineOfSight()} is valid. */ hasValidSatelliteLineOfSight()187 public boolean hasValidSatelliteLineOfSight() { 188 return (mSingleSatCorrectionFlags & HAS_PROB_SAT_IS_LOS_MASK) != 0; 189 } 190 191 /** Returns {@code true} if {@link #getExcessPathLengthMeters()} is valid. */ hasExcessPathLength()192 public boolean hasExcessPathLength() { 193 return (mSingleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_MASK) != 0; 194 } 195 196 /** Returns {@code true} if {@link #getExcessPathLengthUncertaintyMeters()} is valid. */ hasExcessPathLengthUncertainty()197 public boolean hasExcessPathLengthUncertainty() { 198 return (mSingleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK) != 0; 199 } 200 201 /** 202 * Returns {@code true} if {@link #getReflectingPlane()} is valid. 203 * 204 * @deprecated Combined excess path does not have a reflecting plane. 205 */ 206 @Deprecated hasReflectingPlane()207 public boolean hasReflectingPlane() { 208 return false; 209 } 210 211 /** Returns {@code true} if {@link #getCombinedAttenuationDb()} is valid. */ hasCombinedAttenuation()212 public boolean hasCombinedAttenuation() { 213 return (mSingleSatCorrectionFlags & HAS_COMBINED_ATTENUATION_MASK) != 0; 214 } 215 216 @Override describeContents()217 public int describeContents() { 218 return 0; 219 } 220 221 @Override writeToParcel(@onNull Parcel parcel, int flags)222 public void writeToParcel(@NonNull Parcel parcel, int flags) { 223 parcel.writeInt(mSingleSatCorrectionFlags); 224 parcel.writeInt(mConstellationType); 225 parcel.writeInt(mSatId); 226 parcel.writeFloat(mCarrierFrequencyHz); 227 if (hasValidSatelliteLineOfSight()) { 228 parcel.writeFloat(mProbSatIsLos); 229 } 230 if (hasExcessPathLength()) { 231 parcel.writeFloat(mCombinedExcessPathLengthMeters); 232 } 233 if (hasExcessPathLengthUncertainty()) { 234 parcel.writeFloat(mCombinedExcessPathLengthUncertaintyMeters); 235 } 236 if (hasCombinedAttenuation()) { 237 parcel.writeFloat(mCombinedAttenuationDb); 238 } 239 parcel.writeTypedList(mGnssExcessPathInfoList); 240 } 241 242 public static final Creator<GnssSingleSatCorrection> CREATOR = 243 new Creator<GnssSingleSatCorrection>() { 244 @Override 245 @NonNull 246 public GnssSingleSatCorrection createFromParcel(@NonNull Parcel parcel) { 247 int singleSatCorrectionFlags = parcel.readInt(); 248 int constellationType = parcel.readInt(); 249 int satId = parcel.readInt(); 250 float carrierFrequencyHz = parcel.readFloat(); 251 float probSatIsLos = (singleSatCorrectionFlags & HAS_PROB_SAT_IS_LOS_MASK) != 0 252 ? parcel.readFloat() : 0; 253 float combinedExcessPathLengthMeters = 254 (singleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_MASK) != 0 255 ? parcel.readFloat() : 0; 256 float combinedExcessPathLengthUncertaintyMeters = 257 (singleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK) 258 != 0 ? parcel.readFloat() : 0; 259 float combinedAttenuationDb = 260 (singleSatCorrectionFlags & HAS_COMBINED_ATTENUATION_MASK) != 0 261 ? parcel.readFloat() : 0; 262 List<GnssExcessPathInfo> gnssExcessPathInfoList = parcel.createTypedArrayList( 263 GnssExcessPathInfo.CREATOR); 264 return new GnssSingleSatCorrection(singleSatCorrectionFlags, constellationType, 265 satId, carrierFrequencyHz, probSatIsLos, combinedExcessPathLengthMeters, 266 combinedExcessPathLengthUncertaintyMeters, combinedAttenuationDb, 267 gnssExcessPathInfoList); 268 } 269 270 @Override 271 public GnssSingleSatCorrection[] newArray(int i) { 272 return new GnssSingleSatCorrection[i]; 273 } 274 }; 275 276 @Override equals(Object obj)277 public boolean equals(Object obj) { 278 if (obj instanceof GnssSingleSatCorrection) { 279 GnssSingleSatCorrection that = (GnssSingleSatCorrection) obj; 280 return this.mSingleSatCorrectionFlags == that.mSingleSatCorrectionFlags 281 && this.mConstellationType == that.mConstellationType 282 && this.mSatId == that.mSatId 283 && Float.compare(mCarrierFrequencyHz, that.mCarrierFrequencyHz) == 0 284 && (!hasValidSatelliteLineOfSight() || Float.compare(mProbSatIsLos, 285 that.mProbSatIsLos) == 0) 286 && (!hasExcessPathLength() || Float.compare(mCombinedExcessPathLengthMeters, 287 that.mCombinedExcessPathLengthMeters) == 0) 288 && (!hasExcessPathLengthUncertainty() || Float.compare( 289 mCombinedExcessPathLengthUncertaintyMeters, 290 that.mCombinedExcessPathLengthUncertaintyMeters) == 0) 291 && (!hasCombinedAttenuation() || Float.compare(mCombinedAttenuationDb, 292 that.mCombinedAttenuationDb) == 0) 293 && mGnssExcessPathInfoList.equals(that.mGnssExcessPathInfoList); 294 } 295 return false; 296 } 297 298 @Override hashCode()299 public int hashCode() { 300 return Objects.hash(mSingleSatCorrectionFlags, 301 mConstellationType, 302 mSatId, 303 mCarrierFrequencyHz, 304 mProbSatIsLos, 305 mCombinedExcessPathLengthMeters, 306 mCombinedExcessPathLengthUncertaintyMeters, 307 mCombinedAttenuationDb, 308 mGnssExcessPathInfoList); 309 } 310 311 @NonNull 312 @Override toString()313 public String toString() { 314 StringBuilder builder = new StringBuilder("GnssSingleSatCorrection:["); 315 builder.append(" ConstellationType=").append(mConstellationType); 316 builder.append(" SatId=").append(mSatId); 317 builder.append(" CarrierFrequencyHz=").append(mCarrierFrequencyHz); 318 if (hasValidSatelliteLineOfSight()) { 319 builder.append(" ProbSatIsLos=").append(mProbSatIsLos); 320 } 321 if (hasExcessPathLength()) { 322 builder.append(" CombinedExcessPathLengthMeters=").append( 323 mCombinedExcessPathLengthMeters); 324 } 325 if (hasExcessPathLengthUncertainty()) { 326 builder.append(" CombinedExcessPathLengthUncertaintyMeters=").append( 327 mCombinedExcessPathLengthUncertaintyMeters); 328 } 329 if (hasCombinedAttenuation()) { 330 builder.append(" CombinedAttenuationDb=").append( 331 mCombinedAttenuationDb); 332 } 333 if (!mGnssExcessPathInfoList.isEmpty()) { 334 builder.append(' ').append(mGnssExcessPathInfoList.toString()); 335 } 336 builder.append(']'); 337 return builder.toString(); 338 } 339 340 /** Builder for {@link GnssSingleSatCorrection} */ 341 public static final class Builder { 342 private int mSingleSatCorrectionFlags; 343 private int mConstellationType; 344 private int mSatId; 345 private float mCarrierFrequencyHz; 346 private float mProbSatIsLos; 347 private float mCombinedExcessPathLengthMeters; 348 private float mCombinedExcessPathLengthUncertaintyMeters; 349 private float mCombinedAttenuationDb; 350 @NonNull 351 private List<GnssExcessPathInfo> mGnssExcessInfoList = new ArrayList<>(); 352 353 /** Sets the constellation type. */ setConstellationType( @nssStatus.ConstellationType int constellationType)354 @NonNull public Builder setConstellationType( 355 @GnssStatus.ConstellationType int constellationType) { 356 mConstellationType = constellationType; 357 return this; 358 } 359 360 /** Sets the satellite ID defined in the ICD of the given constellation. */ setSatelliteId(@ntRangefrom = 0) int satId)361 @NonNull public Builder setSatelliteId(@IntRange(from = 0) int satId) { 362 Preconditions.checkArgumentNonnegative(satId, "satId should be non-negative."); 363 mSatId = satId; 364 return this; 365 } 366 367 /** Sets the carrier frequency in Hz. */ setCarrierFrequencyHz( @loatRangefrom = 0.0f, fromInclusive = false) float carrierFrequencyHz)368 @NonNull public Builder setCarrierFrequencyHz( 369 @FloatRange(from = 0.0f, fromInclusive = false) float carrierFrequencyHz) { 370 Preconditions.checkArgumentInRange( 371 carrierFrequencyHz, 0, Float.MAX_VALUE, "carrierFrequencyHz"); 372 mCarrierFrequencyHz = carrierFrequencyHz; 373 return this; 374 } 375 376 /** 377 * Sets the line-of-sight probability of the satellite at the given location in the range 378 * between 0 and 1. 379 */ setProbabilityLineOfSight( @loatRangefrom = 0.0f, to = 1.0f) float probSatIsLos)380 @NonNull public Builder setProbabilityLineOfSight( 381 @FloatRange(from = 0.0f, to = 1.0f) float probSatIsLos) { 382 Preconditions.checkArgumentInRange( 383 probSatIsLos, 0, 1, "probSatIsLos should be between 0 and 1."); 384 mProbSatIsLos = probSatIsLos; 385 mSingleSatCorrectionFlags |= HAS_PROB_SAT_IS_LOS_MASK; 386 return this; 387 } 388 389 /** 390 * Clears the line-of-sight probability of the satellite at the given location. 391 * 392 * <p>This is to negate {@link #setProbabilityLineOfSight} call. 393 */ clearProbabilityLineOfSight()394 @NonNull public Builder clearProbabilityLineOfSight() { 395 mProbSatIsLos = 0; 396 mSingleSatCorrectionFlags &= ~HAS_PROB_SAT_IS_LOS_MASK; 397 return this; 398 } 399 400 /** 401 * Sets the combined excess path length to be subtracted from pseudorange before using it in 402 * calculating location. 403 */ 404 @NonNull setExcessPathLengthMeters( @loatRangefrom = 0.0f) float combinedExcessPathLengthMeters)405 public Builder setExcessPathLengthMeters( 406 @FloatRange(from = 0.0f) float combinedExcessPathLengthMeters) { 407 Preconditions.checkArgumentInRange(combinedExcessPathLengthMeters, 0, Float.MAX_VALUE, 408 "excessPathLengthMeters"); 409 mCombinedExcessPathLengthMeters = combinedExcessPathLengthMeters; 410 mSingleSatCorrectionFlags |= HAS_COMBINED_EXCESS_PATH_LENGTH_MASK; 411 return this; 412 } 413 414 /** 415 * Clears the combined excess path length. 416 * 417 * <p>This is to negate {@link #setExcessPathLengthMeters} call. 418 */ clearExcessPathLengthMeters()419 @NonNull public Builder clearExcessPathLengthMeters() { 420 mCombinedExcessPathLengthMeters = 0; 421 mSingleSatCorrectionFlags &= ~HAS_COMBINED_EXCESS_PATH_LENGTH_MASK; 422 return this; 423 } 424 425 /** Sets the error estimate (1-sigma) for the combined excess path length estimate. */ setExcessPathLengthUncertaintyMeters( @loatRangefrom = 0.0f) float combinedExcessPathLengthUncertaintyMeters)426 @NonNull public Builder setExcessPathLengthUncertaintyMeters( 427 @FloatRange(from = 0.0f) float combinedExcessPathLengthUncertaintyMeters) { 428 Preconditions.checkArgumentInRange(combinedExcessPathLengthUncertaintyMeters, 0, 429 Float.MAX_VALUE, "excessPathLengthUncertaintyMeters"); 430 mCombinedExcessPathLengthUncertaintyMeters = combinedExcessPathLengthUncertaintyMeters; 431 mSingleSatCorrectionFlags |= HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK; 432 return this; 433 } 434 435 /** 436 * Clears the error estimate (1-sigma) for the combined excess path length estimate. 437 * 438 * <p>This is to negate {@link #setExcessPathLengthUncertaintyMeters} call. 439 */ clearExcessPathLengthUncertaintyMeters()440 @NonNull public Builder clearExcessPathLengthUncertaintyMeters() { 441 mCombinedExcessPathLengthUncertaintyMeters = 0; 442 mSingleSatCorrectionFlags &= ~HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK; 443 return this; 444 } 445 446 /** 447 * Sets the combined attenuation in Db. 448 */ setCombinedAttenuationDb( @loatRangefrom = 0.0f) float combinedAttenuationDb)449 @NonNull public Builder setCombinedAttenuationDb( 450 @FloatRange(from = 0.0f) float combinedAttenuationDb) { 451 Preconditions.checkArgumentInRange(combinedAttenuationDb, 0, Float.MAX_VALUE, 452 "combinedAttenuationDb"); 453 mCombinedAttenuationDb = combinedAttenuationDb; 454 mSingleSatCorrectionFlags |= HAS_COMBINED_ATTENUATION_MASK; 455 return this; 456 } 457 458 /** 459 * Clears the combined attenuation. 460 * 461 * <p>This is to negate {@link #setCombinedAttenuationDb} call. 462 */ clearCombinedAttenuationDb()463 @NonNull public Builder clearCombinedAttenuationDb() { 464 mCombinedAttenuationDb = 0; 465 mSingleSatCorrectionFlags &= ~HAS_COMBINED_ATTENUATION_MASK; 466 return this; 467 } 468 469 /** 470 * Sets the reflecting plane information. 471 * 472 * @deprecated Combined excess path does not have a reflecting plane. 473 */ 474 @Deprecated setReflectingPlane(@ullable GnssReflectingPlane reflectingPlane)475 @NonNull public Builder setReflectingPlane(@Nullable GnssReflectingPlane reflectingPlane) { 476 return this; 477 } 478 479 /** 480 * Sets the collection of {@link GnssExcessPathInfo}. 481 */ 482 @NonNull setGnssExcessPathInfoList(@onNull List<GnssExcessPathInfo> infoList)483 public Builder setGnssExcessPathInfoList(@NonNull List<GnssExcessPathInfo> infoList) { 484 mGnssExcessInfoList = new ArrayList<>(infoList); 485 return this; 486 } 487 488 /** Builds a {@link GnssSingleSatCorrection} instance as specified by this builder. */ build()489 @NonNull public GnssSingleSatCorrection build() { 490 return new GnssSingleSatCorrection(mSingleSatCorrectionFlags, 491 mConstellationType, 492 mSatId, 493 mCarrierFrequencyHz, 494 mProbSatIsLos, 495 mCombinedExcessPathLengthMeters, 496 mCombinedExcessPathLengthUncertaintyMeters, 497 mCombinedAttenuationDb, 498 mGnssExcessInfoList); 499 } 500 } 501 } 502