• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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