1 /* 2 * Copyright (C) 2020 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 android.annotation.FloatRange; 20 import android.annotation.IntDef; 21 import android.annotation.IntRange; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.SystemApi; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 28 import com.android.internal.util.Preconditions; 29 30 import java.lang.annotation.Retention; 31 import java.lang.annotation.RetentionPolicy; 32 33 /** 34 * A class that contains GNSS satellite position, velocity and time information at the 35 * same signal transmission time {@link GnssMeasurement#getReceivedSvTimeNanos()}. 36 * 37 * <p>The position and velocity must be in ECEF coordinates. 38 * 39 * <p>If {@link GnssMeasurement#getSatellitePvt()} is derived from Broadcast ephemeris, then the 40 * position is already w.r.t. the antenna phase center. However, if 41 * {@link GnssMeasurement#getSatellitePvt()} is derived from other modeled orbits, such as 42 * long-term orbits, or precise orbits, then the orbits may have been computed w.r.t. 43 * the satellite center of mass, and then GNSS vendors are expected to correct for the effect 44 * on different phase centers (can differ by meters) of different GNSS signals (e.g. L1, L5) 45 * on the reported satellite position. Accordingly, we might observe a different satellite 46 * position reported for L1 GnssMeasurement struct compared to L5 GnssMeasurement struct. 47 * 48 * <p>If {@link GnssMeasurement#getReceivedSvTimeNanos()} is not fully decoded, 49 * {@link GnssMeasurement#getSatellitePvt()} could still be reported and 50 * {@link GnssMeasurement#getReceivedSvTimeUncertaintyNanos()} would be used to provide confidence. 51 * @hide 52 */ 53 @SystemApi 54 public final class SatellitePvt implements Parcelable { 55 /** 56 * Bit mask for {@link #mFlags} indicating valid satellite position, velocity and clock info 57 * fields are stored in the SatellitePvt. 58 */ 59 private static final int HAS_POSITION_VELOCITY_CLOCK_INFO = 1 << 0; 60 61 /** 62 * Bit mask for {@link #mFlags} indicating a valid iono delay field is stored in the 63 * SatellitePvt. 64 */ 65 private static final int HAS_IONO = 1 << 1; 66 67 /** 68 * Bit mask for {@link #mFlags} indicating a valid tropo delay field is stored in the 69 * SatellitePvt. 70 */ 71 private static final int HAS_TROPO = 1 << 2; 72 73 /** 74 * Bit mask for {@link #mFlags} indicating a valid Issue of Data, Clock field is stored in the 75 * SatellitePvt. 76 */ 77 private static final int HAS_ISSUE_OF_DATA_CLOCK = 1 << 3; 78 79 /** 80 * Bit mask for {@link #mFlags} indicating a valid Issue of Data, Ephemeris field is stored in 81 * the SatellitePvt. 82 */ 83 private static final int HAS_ISSUE_OF_DATA_EPHEMERIS = 1 << 4; 84 85 /** 86 * Bit mask for {@link #mFlags} indicating a valid Time of Clock field is stored in the 87 * SatellitePvt. 88 */ 89 private static final int HAS_TIME_OF_CLOCK = 1 << 5; 90 91 /** 92 * Bit mask for {@link #mFlags} indicating a valid Time of Ephemeris field is stored in 93 * the SatellitePvt. 94 */ 95 private static final int HAS_TIME_OF_EPHEMERIS = 1 << 6; 96 97 98 /** Ephemeris demodulated from broadcast signals */ 99 public static final int EPHEMERIS_SOURCE_DEMODULATED = 0; 100 101 /** 102 * Server provided Normal type ephemeris data, which is similar to broadcast ephemeris in 103 * longevity (e.g. SUPL) - lasting for few hours and providing satellite orbit and clock 104 * with accuracy of 1 - 2 meters. 105 */ 106 public static final int EPHEMERIS_SOURCE_SERVER_NORMAL = 1; 107 108 /** 109 * Server provided Long-Term type ephemeris data, which lasts for many hours to several days 110 * and often provides satellite orbit and clock accuracy of 2 - 20 meters. 111 */ 112 public static final int EPHEMERIS_SOURCE_SERVER_LONG_TERM = 2; 113 114 /** Other ephemeris source */ 115 public static final int EPHEMERIS_SOURCE_OTHER = 3; 116 117 /** 118 * Satellite ephemeris source 119 * @hide 120 */ 121 @Retention(RetentionPolicy.SOURCE) 122 @IntDef({EPHEMERIS_SOURCE_DEMODULATED, EPHEMERIS_SOURCE_SERVER_NORMAL, 123 EPHEMERIS_SOURCE_SERVER_LONG_TERM, EPHEMERIS_SOURCE_OTHER}) 124 public @interface EphemerisSource { 125 } 126 127 /** 128 * A bitfield of flags indicating the validity of the fields in this SatellitePvt. 129 * The bit masks are defined in the constants with prefix HAS_* 130 * 131 * <p>Fields for which there is no corresponding flag must be filled in with a valid value. 132 * For convenience, these are marked as mandatory. 133 * 134 * <p>Others fields may have invalid information in them, if not marked as valid by the 135 * corresponding bit in flags. 136 */ 137 private final int mFlags; 138 139 @Nullable 140 private final PositionEcef mPositionEcef; 141 @Nullable 142 private final VelocityEcef mVelocityEcef; 143 @Nullable 144 private final ClockInfo mClockInfo; 145 private final double mIonoDelayMeters; 146 private final double mTropoDelayMeters; 147 private final long mTimeOfClockSeconds; 148 private final long mTimeOfEphemerisSeconds; 149 private final int mIssueOfDataClock; 150 private final int mIssueOfDataEphemeris; 151 @EphemerisSource 152 private final int mEphemerisSource; 153 154 /** 155 * Class containing estimates of the satellite position fields in ECEF coordinate frame. 156 * 157 * <p>The satellite position must be defined at the time of transmission of the signal 158 * receivedSvTimeNs. 159 */ 160 public static final class PositionEcef implements Parcelable { 161 private final double mXMeters; 162 private final double mYMeters; 163 private final double mZMeters; 164 private final double mUreMeters; 165 PositionEcef( double xMeters, double yMeters, double zMeters, double ureMeters)166 public PositionEcef( 167 double xMeters, 168 double yMeters, 169 double zMeters, 170 double ureMeters) { 171 mXMeters = xMeters; 172 mYMeters = yMeters; 173 mZMeters = zMeters; 174 mUreMeters = ureMeters; 175 } 176 177 public static final @NonNull Creator<PositionEcef> CREATOR = 178 new Creator<PositionEcef>() { 179 @Override 180 public PositionEcef createFromParcel(Parcel in) { 181 return new PositionEcef( 182 in.readDouble(), 183 in.readDouble(), 184 in.readDouble(), 185 in.readDouble() 186 ); 187 } 188 189 @Override 190 public PositionEcef[] newArray(int size) { 191 return new PositionEcef[size]; 192 } 193 }; 194 195 /** 196 * Returns the satellite position X in WGS84 ECEF (meters). 197 */ 198 @FloatRange() getXMeters()199 public double getXMeters() { 200 return mXMeters; 201 } 202 203 /** 204 * Returns the satellite position Y in WGS84 ECEF (meters). 205 */ 206 @FloatRange() getYMeters()207 public double getYMeters() { 208 return mYMeters; 209 } 210 211 /** 212 * Returns the satellite position Z in WGS84 ECEF (meters). 213 */ 214 @FloatRange() getZMeters()215 public double getZMeters() { 216 return mZMeters; 217 } 218 219 /** 220 * Returns the signal in Space User Range Error (URE) (meters). 221 */ 222 @FloatRange(from = 0.0f, fromInclusive = false) getUreMeters()223 public double getUreMeters() { 224 return mUreMeters; 225 } 226 227 @Override describeContents()228 public int describeContents() { 229 return 0; 230 } 231 232 @Override writeToParcel(@onNull Parcel dest, int flags)233 public void writeToParcel(@NonNull Parcel dest, int flags) { 234 dest.writeDouble(mXMeters); 235 dest.writeDouble(mYMeters); 236 dest.writeDouble(mZMeters); 237 dest.writeDouble(mUreMeters); 238 } 239 240 @Override toString()241 public String toString() { 242 return "PositionEcef{" 243 + "xMeters=" + mXMeters 244 + ", yMeters=" + mYMeters 245 + ", zMeters=" + mZMeters 246 + ", ureMeters=" + mUreMeters 247 + "}"; 248 } 249 } 250 251 /** 252 * Class containing estimates of the satellite velocity fields in the ECEF coordinate frame. 253 * 254 * <p>The satellite velocity must be defined at the time of transmission of the signal 255 * receivedSvTimeNs. 256 */ 257 public static final class VelocityEcef implements Parcelable { 258 private final double mXMetersPerSecond; 259 private final double mYMetersPerSecond; 260 private final double mZMetersPerSecond; 261 private final double mUreRateMetersPerSecond; 262 VelocityEcef( double xMetersPerSecond, double yMetersPerSecond, double zMetersPerSecond, double ureRateMetersPerSecond)263 public VelocityEcef( 264 double xMetersPerSecond, 265 double yMetersPerSecond, 266 double zMetersPerSecond, 267 double ureRateMetersPerSecond) { 268 mXMetersPerSecond = xMetersPerSecond; 269 mYMetersPerSecond = yMetersPerSecond; 270 mZMetersPerSecond = zMetersPerSecond; 271 mUreRateMetersPerSecond = ureRateMetersPerSecond; 272 } 273 274 public static final @NonNull Creator<VelocityEcef> CREATOR = 275 new Creator<VelocityEcef>() { 276 @Override 277 public VelocityEcef createFromParcel(Parcel in) { 278 return new VelocityEcef( 279 in.readDouble(), 280 in.readDouble(), 281 in.readDouble(), 282 in.readDouble() 283 ); 284 } 285 286 @Override 287 public VelocityEcef[] newArray(int size) { 288 return new VelocityEcef[size]; 289 } 290 }; 291 292 /** 293 * Returns the satellite velocity X in WGS84 ECEF (meters per second). 294 */ 295 @FloatRange() getXMetersPerSecond()296 public double getXMetersPerSecond() { 297 return mXMetersPerSecond; 298 } 299 300 /** 301 * Returns the satellite velocity Y in WGS84 ECEF (meters per second). 302 */ 303 @FloatRange() getYMetersPerSecond()304 public double getYMetersPerSecond() { 305 return mYMetersPerSecond; 306 } 307 308 /** 309 *Returns the satellite velocity Z in WGS84 ECEF (meters per second). 310 */ 311 @FloatRange() getZMetersPerSecond()312 public double getZMetersPerSecond() { 313 return mZMetersPerSecond; 314 } 315 316 /** 317 * Returns the signal in Space User Range Error Rate (URE Rate) (meters per second). 318 * 319 * <p>It covers satellite velocity error and Satellite clock drift 320 * projected to the pseudorange rate measurements. 321 */ 322 @FloatRange(from = 0.0f, fromInclusive = false) getUreRateMetersPerSecond()323 public double getUreRateMetersPerSecond() { 324 return mUreRateMetersPerSecond; 325 } 326 327 @Override describeContents()328 public int describeContents() { 329 return 0; 330 } 331 332 @Override writeToParcel(@onNull Parcel dest, int flags)333 public void writeToParcel(@NonNull Parcel dest, int flags) { 334 dest.writeDouble(mXMetersPerSecond); 335 dest.writeDouble(mYMetersPerSecond); 336 dest.writeDouble(mZMetersPerSecond); 337 dest.writeDouble(mUreRateMetersPerSecond); 338 } 339 340 @Override toString()341 public String toString() { 342 return "VelocityEcef{" 343 + "xMetersPerSecond=" + mXMetersPerSecond 344 + ", yMetersPerSecond=" + mYMetersPerSecond 345 + ", zMetersPerSecond=" + mZMetersPerSecond 346 + ", ureRateMetersPerSecond=" + mUreRateMetersPerSecond 347 + "}"; 348 } 349 } 350 351 /** 352 * Class containing estimates of the satellite clock info. 353 */ 354 public static final class ClockInfo implements Parcelable { 355 private final double mHardwareCodeBiasMeters; 356 private final double mTimeCorrectionMeters; 357 private final double mClockDriftMetersPerSecond; 358 ClockInfo( double hardwareCodeBiasMeters, double timeCorrectionMeters, double clockDriftMetersPerSecond)359 public ClockInfo( 360 double hardwareCodeBiasMeters, 361 double timeCorrectionMeters, 362 double clockDriftMetersPerSecond) { 363 mHardwareCodeBiasMeters = hardwareCodeBiasMeters; 364 mTimeCorrectionMeters = timeCorrectionMeters; 365 mClockDriftMetersPerSecond = clockDriftMetersPerSecond; 366 } 367 368 public static final @NonNull Creator<ClockInfo> CREATOR = 369 new Creator<ClockInfo>() { 370 @Override 371 public ClockInfo createFromParcel(Parcel in) { 372 return new ClockInfo( 373 in.readDouble(), 374 in.readDouble(), 375 in.readDouble() 376 ); 377 } 378 379 @Override 380 public ClockInfo[] newArray(int size) { 381 return new ClockInfo[size]; 382 } 383 }; 384 385 /** 386 * Returns the satellite hardware code bias of the reported code type w.r.t 387 * ionosphere-free measurement in meters. 388 * 389 * <p>When broadcast ephemeris is used, this is the offset caused 390 * by the satellite hardware delays at different frequencies; 391 * e.g. in IS-GPS-705D, this term is described in Section 392 * 20.3.3.3.1.2.1. 393 * 394 * <p>For GPS this term is ~10ns, and affects the satellite position 395 * computation by less than a millimeter. 396 */ 397 @FloatRange() getHardwareCodeBiasMeters()398 public double getHardwareCodeBiasMeters() { 399 return mHardwareCodeBiasMeters; 400 } 401 402 /** 403 * Returns the satellite time correction for ionospheric-free signal measurement 404 * (meters). The satellite clock correction for the given signal type 405 * = satTimeCorrectionMeters - satHardwareCodeBiasMeters. 406 * 407 * <p>When broadcast ephemeris is used, this is the offset modeled in the 408 * clock terms broadcast over the air by the satellites; 409 * e.g. in IS-GPS-200H, Section 20.3.3.3.3.1, this term is 410 * ∆tsv = af0 + af1(t - toc) + af2(t - toc)^2 + ∆tr. 411 * 412 * <p>If another source of ephemeris is used for SatellitePvt, then the 413 * equivalent value of satTimeCorrection must be provided. 414 * 415 * <p>For GPS this term is ~1ms, and affects the satellite position 416 * computation by ~1m. 417 */ 418 @FloatRange() getTimeCorrectionMeters()419 public double getTimeCorrectionMeters() { 420 return mTimeCorrectionMeters; 421 } 422 423 /** 424 * Returns the satellite clock drift (meters per second). 425 */ 426 @FloatRange() getClockDriftMetersPerSecond()427 public double getClockDriftMetersPerSecond() { 428 return mClockDriftMetersPerSecond; 429 } 430 431 @Override describeContents()432 public int describeContents() { 433 return 0; 434 } 435 436 @Override writeToParcel(@onNull Parcel dest, int flags)437 public void writeToParcel(@NonNull Parcel dest, int flags) { 438 dest.writeDouble(mHardwareCodeBiasMeters); 439 dest.writeDouble(mTimeCorrectionMeters); 440 dest.writeDouble(mClockDriftMetersPerSecond); 441 } 442 443 @Override toString()444 public String toString() { 445 return "ClockInfo{" 446 + "hardwareCodeBiasMeters=" + mHardwareCodeBiasMeters 447 + ", timeCorrectionMeters=" + mTimeCorrectionMeters 448 + ", clockDriftMetersPerSecond=" + mClockDriftMetersPerSecond 449 + "}"; 450 } 451 } 452 SatellitePvt( int flags, @Nullable PositionEcef positionEcef, @Nullable VelocityEcef velocityEcef, @Nullable ClockInfo clockInfo, double ionoDelayMeters, double tropoDelayMeters, long timeOfClockSeconds, long timeOfEphemerisSeconds, int issueOfDataClock, int issueOfDataEphemeris, @EphemerisSource int ephemerisSource)453 private SatellitePvt( 454 int flags, 455 @Nullable PositionEcef positionEcef, 456 @Nullable VelocityEcef velocityEcef, 457 @Nullable ClockInfo clockInfo, 458 double ionoDelayMeters, 459 double tropoDelayMeters, 460 long timeOfClockSeconds, 461 long timeOfEphemerisSeconds, 462 int issueOfDataClock, 463 int issueOfDataEphemeris, 464 @EphemerisSource int ephemerisSource) { 465 mFlags = flags; 466 mPositionEcef = positionEcef; 467 mVelocityEcef = velocityEcef; 468 mClockInfo = clockInfo; 469 mIonoDelayMeters = ionoDelayMeters; 470 mTropoDelayMeters = tropoDelayMeters; 471 mTimeOfClockSeconds = timeOfClockSeconds; 472 mTimeOfEphemerisSeconds = timeOfEphemerisSeconds; 473 mIssueOfDataClock = issueOfDataClock; 474 mIssueOfDataEphemeris = issueOfDataEphemeris; 475 mEphemerisSource = ephemerisSource; 476 } 477 478 /** 479 * Returns a {@link PositionEcef} object that contains estimates of the satellite 480 * position fields in ECEF coordinate frame. 481 */ 482 @Nullable getPositionEcef()483 public PositionEcef getPositionEcef() { 484 return mPositionEcef; 485 } 486 487 /** 488 * Returns a {@link VelocityEcef} object that contains estimates of the satellite 489 * velocity fields in the ECEF coordinate frame. 490 */ 491 @Nullable getVelocityEcef()492 public VelocityEcef getVelocityEcef() { 493 return mVelocityEcef; 494 } 495 496 /** 497 * Returns a {@link ClockInfo} object that contains estimates of the satellite 498 * clock info. 499 */ 500 @Nullable getClockInfo()501 public ClockInfo getClockInfo() { 502 return mClockInfo; 503 } 504 505 /** 506 * Returns the ionospheric delay in meters. 507 */ 508 @FloatRange() getIonoDelayMeters()509 public double getIonoDelayMeters() { 510 return mIonoDelayMeters; 511 } 512 513 /** 514 * Returns the tropospheric delay in meters. 515 */ 516 @FloatRange() getTropoDelayMeters()517 public double getTropoDelayMeters() { 518 return mTropoDelayMeters; 519 } 520 521 /** 522 * Issue of Data, Clock. 523 * 524 * <p>This is defined in GPS ICD200 documentation (e.g., 525 * <a href="https://www.gps.gov/technical/icwg/IS-GPS-200H.pdf"></a>). 526 * 527 * <p>This field is valid if {@link #hasIssueOfDataClock()} is true. 528 */ 529 @IntRange(from = 0, to = 1023) getIssueOfDataClock()530 public int getIssueOfDataClock() { 531 return mIssueOfDataClock; 532 } 533 534 /** 535 * Issue of Data, Ephemeris. 536 * 537 * <p>This is defined in GPS ICD200 documentation (e.g., 538 * <a href="https://www.gps.gov/technical/icwg/IS-GPS-200H.pdf"></a>). 539 * 540 * <p>This field is valid if {@link #hasIssueOfDataEphemeris()} is true. 541 */ 542 @IntRange(from = 0, to = 1023) getIssueOfDataEphemeris()543 public int getIssueOfDataEphemeris() { 544 return mIssueOfDataEphemeris; 545 } 546 547 /** 548 * Time of Clock in seconds. 549 * 550 * <p>The value is in seconds since GPS epoch, regardless of the constellation. 551 * 552 * <p>The value is not encoded as in GPS ICD200 documentation. 553 * 554 * <p>This field is valid if {@link #hasTimeOfClockSeconds()} is true. 555 */ 556 @IntRange(from = 0) getTimeOfClockSeconds()557 public long getTimeOfClockSeconds() { 558 return mTimeOfClockSeconds; 559 } 560 561 /** 562 * Time of ephemeris in seconds. 563 * 564 * <p>The value is in seconds since GPS epoch, regardless of the constellation. 565 * 566 * <p>The value is not encoded as in GPS ICD200 documentation. 567 * 568 * <p>This field is valid if {@link #hasTimeOfEphemerisSeconds()} is true. 569 */ 570 @IntRange(from = 0) getTimeOfEphemerisSeconds()571 public long getTimeOfEphemerisSeconds() { 572 return mTimeOfEphemerisSeconds; 573 } 574 575 /** 576 * Satellite ephemeris source. 577 */ 578 @EphemerisSource getEphemerisSource()579 public int getEphemerisSource() { 580 return mEphemerisSource; 581 } 582 583 /** Returns {@code true} if {@link #getPositionEcef()}, {@link #getVelocityEcef()}, 584 * and {@link #getClockInfo()} are valid. 585 */ hasPositionVelocityClockInfo()586 public boolean hasPositionVelocityClockInfo() { 587 return (mFlags & HAS_POSITION_VELOCITY_CLOCK_INFO) != 0; 588 } 589 590 /** Returns {@code true} if {@link #getIonoDelayMeters()} is valid. */ hasIono()591 public boolean hasIono() { 592 return (mFlags & HAS_IONO) != 0; 593 } 594 595 /** Returns {@code true} if {@link #getTropoDelayMeters()} is valid. */ hasTropo()596 public boolean hasTropo() { 597 return (mFlags & HAS_TROPO) != 0; 598 } 599 600 /** Returns {@code true} if {@link #getIssueOfDataClock()} is valid. */ hasIssueOfDataClock()601 public boolean hasIssueOfDataClock() { 602 return (mFlags & HAS_ISSUE_OF_DATA_CLOCK) != 0; 603 } 604 605 /** Returns {@code true} if {@link #getIssueOfDataEphemeris()} is valid. */ hasIssueOfDataEphemeris()606 public boolean hasIssueOfDataEphemeris() { 607 return (mFlags & HAS_ISSUE_OF_DATA_EPHEMERIS) != 0; 608 } 609 610 /** Returns {@code true} if {@link #getTimeOfClockSeconds()} ()} is valid. */ hasTimeOfClockSeconds()611 public boolean hasTimeOfClockSeconds() { 612 return (mFlags & HAS_TIME_OF_CLOCK) != 0; 613 } 614 615 /** Returns {@code true} if {@link #getTimeOfEphemerisSeconds()} is valid. */ hasTimeOfEphemerisSeconds()616 public boolean hasTimeOfEphemerisSeconds() { 617 return (mFlags & HAS_TIME_OF_EPHEMERIS) != 0; 618 } 619 620 public static final @android.annotation.NonNull Creator<SatellitePvt> CREATOR = 621 new Creator<SatellitePvt>() { 622 @Override 623 @Nullable 624 public SatellitePvt createFromParcel(Parcel in) { 625 int flags = in.readInt(); 626 ClassLoader classLoader = getClass().getClassLoader(); 627 PositionEcef positionEcef = in.readParcelable(classLoader, 628 android.location.SatellitePvt.PositionEcef.class); 629 VelocityEcef velocityEcef = in.readParcelable(classLoader, 630 android.location.SatellitePvt.VelocityEcef.class); 631 ClockInfo clockInfo = in.readParcelable(classLoader, 632 android.location.SatellitePvt.ClockInfo.class); 633 double ionoDelayMeters = in.readDouble(); 634 double tropoDelayMeters = in.readDouble(); 635 long toc = in.readLong(); 636 long toe = in.readLong(); 637 int iodc = in.readInt(); 638 int iode = in.readInt(); 639 int ephemerisSource = in.readInt(); 640 641 return new SatellitePvt( 642 flags, 643 positionEcef, 644 velocityEcef, 645 clockInfo, 646 ionoDelayMeters, 647 tropoDelayMeters, 648 toc, 649 toe, 650 iodc, 651 iode, 652 ephemerisSource); 653 } 654 655 @Override 656 public SatellitePvt[] newArray(int size) { 657 return new SatellitePvt[size]; 658 } 659 }; 660 661 @Override describeContents()662 public int describeContents() { 663 return 0; 664 } 665 666 @Override writeToParcel(@onNull Parcel parcel, int flags)667 public void writeToParcel(@NonNull Parcel parcel, int flags) { 668 parcel.writeInt(mFlags); 669 parcel.writeParcelable(mPositionEcef, flags); 670 parcel.writeParcelable(mVelocityEcef, flags); 671 parcel.writeParcelable(mClockInfo, flags); 672 parcel.writeDouble(mIonoDelayMeters); 673 parcel.writeDouble(mTropoDelayMeters); 674 parcel.writeLong(mTimeOfClockSeconds); 675 parcel.writeLong(mTimeOfEphemerisSeconds); 676 parcel.writeInt(mIssueOfDataClock); 677 parcel.writeInt(mIssueOfDataEphemeris); 678 parcel.writeInt(mEphemerisSource); 679 } 680 681 @Override toString()682 public String toString() { 683 return "SatellitePvt[" 684 + "Flags=" + mFlags 685 + ", PositionEcef=" + mPositionEcef 686 + ", VelocityEcef=" + mVelocityEcef 687 + ", ClockInfo=" + mClockInfo 688 + ", IonoDelayMeters=" + mIonoDelayMeters 689 + ", TropoDelayMeters=" + mTropoDelayMeters 690 + ", TimeOfClockSeconds=" + mTimeOfClockSeconds 691 + ", TimeOfEphemerisSeconds=" + mTimeOfEphemerisSeconds 692 + ", IssueOfDataClock=" + mIssueOfDataClock 693 + ", IssueOfDataEphemeris=" + mIssueOfDataEphemeris 694 + ", EphemerisSource=" + mEphemerisSource 695 + "]"; 696 } 697 698 /** 699 * Builder class for SatellitePvt. 700 */ 701 public static final class Builder { 702 /** 703 * For documentation of below fields, see corresponding fields in {@link 704 * SatellitePvt}. 705 */ 706 private int mFlags; 707 @Nullable private PositionEcef mPositionEcef; 708 @Nullable private VelocityEcef mVelocityEcef; 709 @Nullable private ClockInfo mClockInfo; 710 private double mIonoDelayMeters; 711 private double mTropoDelayMeters; 712 private long mTimeOfClockSeconds; 713 private long mTimeOfEphemerisSeconds; 714 private int mIssueOfDataClock; 715 private int mIssueOfDataEphemeris; 716 @EphemerisSource 717 private int mEphemerisSource = EPHEMERIS_SOURCE_OTHER; 718 719 /** 720 * Set position ECEF. 721 * 722 * @param positionEcef position ECEF object 723 * @return builder object 724 */ 725 @NonNull setPositionEcef(@onNull PositionEcef positionEcef)726 public Builder setPositionEcef(@NonNull PositionEcef positionEcef) { 727 mPositionEcef = positionEcef; 728 updateFlags(); 729 return this; 730 } 731 732 /** 733 * Set velocity ECEF. 734 * 735 * @param velocityEcef velocity ECEF object 736 * @return builder object 737 */ 738 @NonNull setVelocityEcef(@onNull VelocityEcef velocityEcef)739 public Builder setVelocityEcef(@NonNull VelocityEcef velocityEcef) { 740 mVelocityEcef = velocityEcef; 741 updateFlags(); 742 return this; 743 } 744 745 /** 746 * Set clock info. 747 * 748 * @param clockInfo clock info object 749 * @return builder object 750 */ 751 @NonNull setClockInfo(@onNull ClockInfo clockInfo)752 public Builder setClockInfo(@NonNull ClockInfo clockInfo) { 753 mClockInfo = clockInfo; 754 updateFlags(); 755 return this; 756 } 757 updateFlags()758 private void updateFlags() { 759 if (mPositionEcef != null && mVelocityEcef != null && mClockInfo != null) { 760 mFlags = (byte) (mFlags | HAS_POSITION_VELOCITY_CLOCK_INFO); 761 } 762 } 763 764 /** 765 * Set ionospheric delay in meters. 766 * 767 * @param ionoDelayMeters ionospheric delay (meters) 768 * @return builder object 769 */ 770 @NonNull setIonoDelayMeters( @loatRangefrom = 0.0f, to = 100.0f) double ionoDelayMeters)771 public Builder setIonoDelayMeters( 772 @FloatRange(from = 0.0f, to = 100.0f) double ionoDelayMeters) { 773 mIonoDelayMeters = ionoDelayMeters; 774 mFlags = (byte) (mFlags | HAS_IONO); 775 return this; 776 } 777 778 /** 779 * Set tropospheric delay in meters. 780 * 781 * @param tropoDelayMeters tropospheric delay (meters) 782 * @return builder object 783 */ 784 @NonNull setTropoDelayMeters( @loatRangefrom = 0.0f, to = 100.0f) double tropoDelayMeters)785 public Builder setTropoDelayMeters( 786 @FloatRange(from = 0.0f, to = 100.0f) double tropoDelayMeters) { 787 mTropoDelayMeters = tropoDelayMeters; 788 mFlags = (byte) (mFlags | HAS_TROPO); 789 return this; 790 } 791 792 /** 793 * Set time of clock in seconds. 794 * 795 * <p>The value is in seconds since GPS epoch, regardless of the constellation. 796 * 797 * <p>The value is not encoded as in GPS ICD200 documentation. 798 * 799 * @param timeOfClockSeconds time of clock (seconds) 800 * @return builder object 801 */ 802 @NonNull setTimeOfClockSeconds(@ntRangefrom = 0) long timeOfClockSeconds)803 public Builder setTimeOfClockSeconds(@IntRange(from = 0) long timeOfClockSeconds) { 804 Preconditions.checkArgumentNonnegative(timeOfClockSeconds); 805 mTimeOfClockSeconds = timeOfClockSeconds; 806 mFlags = (byte) (mFlags | HAS_TIME_OF_CLOCK); 807 return this; 808 } 809 810 /** 811 * Set time of ephemeris in seconds. 812 * 813 * <p>The value is in seconds since GPS epoch, regardless of the constellation. 814 * 815 * <p>The value is not encoded as in GPS ICD200 documentation. 816 * 817 * @param timeOfEphemerisSeconds time of ephemeris (seconds) 818 * @return builder object 819 */ 820 @NonNull setTimeOfEphemerisSeconds(@ntRangefrom = 0) long timeOfEphemerisSeconds)821 public Builder setTimeOfEphemerisSeconds(@IntRange(from = 0) long timeOfEphemerisSeconds) { 822 Preconditions.checkArgumentNonnegative(timeOfEphemerisSeconds); 823 mTimeOfEphemerisSeconds = timeOfEphemerisSeconds; 824 mFlags = (byte) (mFlags | HAS_TIME_OF_EPHEMERIS); 825 return this; 826 } 827 828 /** 829 * Set issue of data, clock. 830 * 831 * @param issueOfDataClock issue of data, clock. 832 * @return builder object 833 */ 834 @NonNull setIssueOfDataClock(@ntRangefrom = 0, to = 1023) int issueOfDataClock)835 public Builder setIssueOfDataClock(@IntRange(from = 0, to = 1023) int issueOfDataClock) { 836 Preconditions.checkArgumentInRange(issueOfDataClock, 0, 1023, "issueOfDataClock"); 837 mIssueOfDataClock = issueOfDataClock; 838 mFlags = (byte) (mFlags | HAS_ISSUE_OF_DATA_CLOCK); 839 return this; 840 } 841 842 /** 843 * Set issue of data, ephemeris. 844 * 845 * @param issueOfDataEphemeris issue of data, ephemeris. 846 * @return builder object 847 */ 848 @NonNull setIssueOfDataEphemeris( @ntRangefrom = 0, to = 1023) int issueOfDataEphemeris)849 public Builder setIssueOfDataEphemeris( 850 @IntRange(from = 0, to = 1023) int issueOfDataEphemeris) { 851 Preconditions.checkArgumentInRange(issueOfDataEphemeris, 0, 1023, 852 "issueOfDataEphemeris"); 853 mIssueOfDataEphemeris = issueOfDataEphemeris; 854 mFlags = (byte) (mFlags | HAS_ISSUE_OF_DATA_EPHEMERIS); 855 return this; 856 } 857 858 /** 859 * Set satellite ephemeris source. 860 * 861 * @param ephemerisSource satellite ephemeris source 862 * @return builder object 863 */ 864 @NonNull setEphemerisSource(@phemerisSource int ephemerisSource)865 public Builder setEphemerisSource(@EphemerisSource int ephemerisSource) { 866 Preconditions.checkArgument(ephemerisSource == EPHEMERIS_SOURCE_DEMODULATED 867 || ephemerisSource == EPHEMERIS_SOURCE_SERVER_NORMAL 868 || ephemerisSource == EPHEMERIS_SOURCE_SERVER_LONG_TERM 869 || ephemerisSource == EPHEMERIS_SOURCE_OTHER); 870 mEphemerisSource = ephemerisSource; 871 return this; 872 } 873 874 /** 875 * Build SatellitePvt object. 876 * 877 * @return instance of SatellitePvt 878 */ 879 @NonNull build()880 public SatellitePvt build() { 881 return new SatellitePvt(mFlags, mPositionEcef, mVelocityEcef, mClockInfo, 882 mIonoDelayMeters, mTropoDelayMeters, mTimeOfClockSeconds, 883 mTimeOfEphemerisSeconds, 884 mIssueOfDataClock, mIssueOfDataEphemeris, 885 mEphemerisSource); 886 } 887 } 888 } 889