1 /*
2  * Copyright (C) 2014 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.NonNull;
21 import android.annotation.TestApi;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 /**
26  * A class containing a GNSS clock timestamp.
27  *
28  * <p>It represents a measurement of the GNSS receiver's clock.
29  */
30 public final class GnssClock implements Parcelable {
31     // The following enumerations must be in sync with the values declared in gps.h
32 
33     private static final int HAS_NO_FLAGS = 0;
34     private static final int HAS_LEAP_SECOND = (1<<0);
35     private static final int HAS_TIME_UNCERTAINTY = (1<<1);
36     private static final int HAS_FULL_BIAS = (1<<2);
37     private static final int HAS_BIAS = (1<<3);
38     private static final int HAS_BIAS_UNCERTAINTY = (1<<4);
39     private static final int HAS_DRIFT = (1<<5);
40     private static final int HAS_DRIFT_UNCERTAINTY = (1<<6);
41     private static final int HAS_ELAPSED_REALTIME_NANOS = (1 << 7);
42     private static final int HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS = (1 << 8);
43     private static final int HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB = (1 << 9);
44     private static final int HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB = (1 << 10);
45     private static final int HAS_REFERENCE_CODE_TYPE_FOR_ISB = (1 << 11);
46 
47     // End enumerations in sync with gps.h
48 
49     private int mFlags;
50     private int mLeapSecond;
51     private long mTimeNanos;
52     private double mTimeUncertaintyNanos;
53     private long mFullBiasNanos;
54     private double mBiasNanos;
55     private double mBiasUncertaintyNanos;
56     private double mDriftNanosPerSecond;
57     private double mDriftUncertaintyNanosPerSecond;
58     private int mHardwareClockDiscontinuityCount;
59     private long mElapsedRealtimeNanos;
60     private double mElapsedRealtimeUncertaintyNanos;
61     private int mReferenceConstellationTypeForIsb;
62     private double mReferenceCarrierFrequencyHzForIsb;
63     private String mReferenceCodeTypeForIsb;
64 
65     /**
66      * @hide
67      */
68     @TestApi
GnssClock()69     public GnssClock() {
70         initialize();
71     }
72 
73     /**
74      * Sets all contents to the values stored in the provided object.
75      * @hide
76      */
77     @TestApi
set(GnssClock clock)78     public void set(GnssClock clock) {
79         mFlags = clock.mFlags;
80         mLeapSecond = clock.mLeapSecond;
81         mTimeNanos = clock.mTimeNanos;
82         mTimeUncertaintyNanos = clock.mTimeUncertaintyNanos;
83         mFullBiasNanos = clock.mFullBiasNanos;
84         mBiasNanos = clock.mBiasNanos;
85         mBiasUncertaintyNanos = clock.mBiasUncertaintyNanos;
86         mDriftNanosPerSecond = clock.mDriftNanosPerSecond;
87         mDriftUncertaintyNanosPerSecond = clock.mDriftUncertaintyNanosPerSecond;
88         mHardwareClockDiscontinuityCount = clock.mHardwareClockDiscontinuityCount;
89         mElapsedRealtimeNanos = clock.mElapsedRealtimeNanos;
90         mElapsedRealtimeUncertaintyNanos = clock.mElapsedRealtimeUncertaintyNanos;
91         mReferenceConstellationTypeForIsb = clock.mReferenceConstellationTypeForIsb;
92         mReferenceCarrierFrequencyHzForIsb = clock.mReferenceCarrierFrequencyHzForIsb;
93         mReferenceCodeTypeForIsb = clock.mReferenceCodeTypeForIsb;
94     }
95 
96     /**
97      * Resets all the contents to its original state.
98      * @hide
99      */
100     @TestApi
reset()101     public void reset() {
102         initialize();
103     }
104 
105     /**
106      * Returns {@code true} if {@link #getLeapSecond()} is available, {@code false} otherwise.
107      */
hasLeapSecond()108     public boolean hasLeapSecond() {
109         return isFlagSet(HAS_LEAP_SECOND);
110     }
111 
112     /**
113      * Gets the leap second associated with the clock's time.
114      *
115      * <p>The sign of the value is defined by the following equation:
116      * <pre>
117      *     UtcTimeNanos = TimeNanos - (FullBiasNanos + BiasNanos) - LeapSecond * 1,000,000,000</pre>
118      *
119      * <p>The value is only available if {@link #hasLeapSecond()} is {@code true}.
120      */
getLeapSecond()121     public int getLeapSecond() {
122         return mLeapSecond;
123     }
124 
125     /**
126      * Sets the leap second associated with the clock's time.
127      * @hide
128      */
129     @TestApi
setLeapSecond(int leapSecond)130     public void setLeapSecond(int leapSecond) {
131         setFlag(HAS_LEAP_SECOND);
132         mLeapSecond = leapSecond;
133     }
134 
135     /**
136      * Resets the leap second associated with the clock's time.
137      * @hide
138      */
139     @TestApi
resetLeapSecond()140     public void resetLeapSecond() {
141         resetFlag(HAS_LEAP_SECOND);
142         mLeapSecond = Integer.MIN_VALUE;
143     }
144 
145     /**
146      * Gets the GNSS receiver internal hardware clock value in nanoseconds.
147      *
148      * <p>This value is expected to be monotonically increasing while the hardware clock remains
149      * powered on. For the case of a hardware clock that is not continuously on, see the
150      * {@link #getHardwareClockDiscontinuityCount} field. The GPS time can be derived by subtracting
151      * the sum of {@link #getFullBiasNanos()} and {@link #getBiasNanos()} (when they are available)
152      * from this value. Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}.
153      *
154      * <p>The error estimate for this value (if applicable) is {@link #getTimeUncertaintyNanos()}.
155      */
getTimeNanos()156     public long getTimeNanos() {
157         return mTimeNanos;
158     }
159 
160     /**
161      * Sets the GNSS receiver internal clock in nanoseconds.
162      * @hide
163      */
164     @TestApi
setTimeNanos(long timeNanos)165     public void setTimeNanos(long timeNanos) {
166         mTimeNanos = timeNanos;
167     }
168 
169     /**
170      * Returns {@code true} if {@link #getTimeUncertaintyNanos()} is available, {@code false}
171      * otherwise.
172      */
hasTimeUncertaintyNanos()173     public boolean hasTimeUncertaintyNanos() {
174         return isFlagSet(HAS_TIME_UNCERTAINTY);
175     }
176 
177     /**
178      * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
179      *
180      * <p>The uncertainty is represented as an absolute (single sided) value.
181      *
182      * <p>The value is only available if {@link #hasTimeUncertaintyNanos()} is {@code true}.
183      *
184      * <p>This value is often effectively zero (it is the reference clock by which all other times
185      * and time uncertainties are measured), and thus this field may often be 0, or not provided.
186      */
187     @FloatRange(from = 0.0f)
getTimeUncertaintyNanos()188     public double getTimeUncertaintyNanos() {
189         return mTimeUncertaintyNanos;
190     }
191 
192     /**
193      * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
194      * @hide
195      */
196     @TestApi
setTimeUncertaintyNanos(@loatRangefrom = 0.0f) double timeUncertaintyNanos)197     public void setTimeUncertaintyNanos(@FloatRange(from = 0.0f) double timeUncertaintyNanos) {
198         setFlag(HAS_TIME_UNCERTAINTY);
199         mTimeUncertaintyNanos = timeUncertaintyNanos;
200     }
201 
202     /**
203      * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
204      * @hide
205      */
206     @TestApi
resetTimeUncertaintyNanos()207     public void resetTimeUncertaintyNanos() {
208         resetFlag(HAS_TIME_UNCERTAINTY);
209     }
210 
211     /**
212      * Returns {@code true} if {@link #getFullBiasNanos()} is available, {@code false} otherwise.
213      */
hasFullBiasNanos()214     public boolean hasFullBiasNanos() {
215         return isFlagSet(HAS_FULL_BIAS);
216     }
217 
218     /**
219      * Gets the difference between hardware clock ({@link #getTimeNanos()}) inside GPS receiver and
220      * the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
221      *
222      * <p>This value is available if the receiver has estimated GPS time. If the computed time is
223      * for a non-GPS constellation, the time offset of that constellation to GPS has to be applied
224      * to fill this value. The value is only available if {@link #hasFullBiasNanos()} is
225      * {@code true}.
226      *
227      * <p>The error estimate for the sum of this field and {@link #getBiasNanos} is
228      * {@link #getBiasUncertaintyNanos()}.
229      *
230      * <p>The sign of the value is defined by the following equation:
231      *
232      * <pre>
233      *     local estimate of GPS time = TimeNanos - (FullBiasNanos + BiasNanos)</pre>
234      */
getFullBiasNanos()235     public long getFullBiasNanos() {
236         return mFullBiasNanos;
237     }
238 
239     /**
240      * Sets the full bias in nanoseconds.
241      * @hide
242      */
243     @TestApi
setFullBiasNanos(long value)244     public void setFullBiasNanos(long value) {
245         setFlag(HAS_FULL_BIAS);
246         mFullBiasNanos = value;
247     }
248 
249     /**
250      * Resets the full bias in nanoseconds.
251      * @hide
252      */
253     @TestApi
resetFullBiasNanos()254     public void resetFullBiasNanos() {
255         resetFlag(HAS_FULL_BIAS);
256         mFullBiasNanos = Long.MIN_VALUE;
257     }
258 
259     /**
260      * Returns {@code true} if {@link #getBiasNanos()} is available, {@code false} otherwise.
261      */
hasBiasNanos()262     public boolean hasBiasNanos() {
263         return isFlagSet(HAS_BIAS);
264     }
265 
266     /**
267      * Gets the clock's sub-nanosecond bias.
268      *
269      * <p>See the description of how this field is part of converting from hardware clock time, to
270      * GPS time, in {@link #getFullBiasNanos()}.
271      *
272      * <p>The error estimate for the sum of this field and {@link #getFullBiasNanos} is
273      * {@link #getBiasUncertaintyNanos()}.
274      *
275      * <p>The value is only available if {@link #hasBiasNanos()} is {@code true}.
276      */
getBiasNanos()277     public double getBiasNanos() {
278         return mBiasNanos;
279     }
280 
281     /**
282      * Sets the sub-nanosecond bias.
283      * @hide
284      */
285     @TestApi
setBiasNanos(double biasNanos)286     public void setBiasNanos(double biasNanos) {
287         setFlag(HAS_BIAS);
288         mBiasNanos = biasNanos;
289     }
290 
291     /**
292      * Resets the clock's Bias in nanoseconds.
293      * @hide
294      */
295     @TestApi
resetBiasNanos()296     public void resetBiasNanos() {
297         resetFlag(HAS_BIAS);
298     }
299 
300     /**
301      * Returns {@code true} if {@link #getBiasUncertaintyNanos()} is available, {@code false}
302      * otherwise.
303      */
hasBiasUncertaintyNanos()304     public boolean hasBiasUncertaintyNanos() {
305         return isFlagSet(HAS_BIAS_UNCERTAINTY);
306     }
307 
308     /**
309      * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
310      *
311      * <p>See the description of how this field provides the error estimate in the conversion from
312      * hardware clock time, to GPS time, in {@link #getFullBiasNanos()}.
313      *
314      * <p>The value is only available if {@link #hasBiasUncertaintyNanos()} is {@code true}.
315      */
316     @FloatRange(from = 0.0f)
getBiasUncertaintyNanos()317     public double getBiasUncertaintyNanos() {
318         return mBiasUncertaintyNanos;
319     }
320 
321     /**
322      * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
323      * @hide
324      */
325     @TestApi
setBiasUncertaintyNanos(@loatRangefrom = 0.0f) double biasUncertaintyNanos)326     public void setBiasUncertaintyNanos(@FloatRange(from = 0.0f) double biasUncertaintyNanos) {
327         setFlag(HAS_BIAS_UNCERTAINTY);
328         mBiasUncertaintyNanos = biasUncertaintyNanos;
329     }
330 
331     /**
332      * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
333      * @hide
334      */
335     @TestApi
resetBiasUncertaintyNanos()336     public void resetBiasUncertaintyNanos() {
337         resetFlag(HAS_BIAS_UNCERTAINTY);
338     }
339 
340     /**
341      * Returns {@code true} if {@link #getDriftNanosPerSecond()} is available, {@code false}
342      * otherwise.
343      */
hasDriftNanosPerSecond()344     public boolean hasDriftNanosPerSecond() {
345         return isFlagSet(HAS_DRIFT);
346     }
347 
348     /**
349      * Gets the clock's Drift in nanoseconds per second.
350      *
351      * <p>This value is the instantaneous time-derivative of the value provided by
352      * {@link #getBiasNanos()}.
353      *
354      * <p>A positive value indicates that the frequency is higher than the nominal (e.g. GPS master
355      * clock) frequency. The error estimate for this reported drift is
356      * {@link #getDriftUncertaintyNanosPerSecond()}.
357      *
358      * <p>The value is only available if {@link #hasDriftNanosPerSecond()} is {@code true}.
359      */
getDriftNanosPerSecond()360     public double getDriftNanosPerSecond() {
361         return mDriftNanosPerSecond;
362     }
363 
364     /**
365      * Sets the clock's Drift in nanoseconds per second.
366      * @hide
367      */
368     @TestApi
setDriftNanosPerSecond(double driftNanosPerSecond)369     public void setDriftNanosPerSecond(double driftNanosPerSecond) {
370         setFlag(HAS_DRIFT);
371         mDriftNanosPerSecond = driftNanosPerSecond;
372     }
373 
374     /**
375      * Resets the clock's Drift in nanoseconds per second.
376      * @hide
377      */
378     @TestApi
resetDriftNanosPerSecond()379     public void resetDriftNanosPerSecond() {
380         resetFlag(HAS_DRIFT);
381     }
382 
383     /**
384      * Returns {@code true} if {@link #getDriftUncertaintyNanosPerSecond()} is available,
385      * {@code false} otherwise.
386      */
hasDriftUncertaintyNanosPerSecond()387     public boolean hasDriftUncertaintyNanosPerSecond() {
388         return isFlagSet(HAS_DRIFT_UNCERTAINTY);
389     }
390 
391     /**
392      * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
393      *
394      * <p>The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is
395      * {@code true}.
396      */
397     @FloatRange(from = 0.0f)
getDriftUncertaintyNanosPerSecond()398     public double getDriftUncertaintyNanosPerSecond() {
399         return mDriftUncertaintyNanosPerSecond;
400     }
401 
402     /**
403      * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
404      * @hide
405      */
406     @TestApi
setDriftUncertaintyNanosPerSecond( @loatRangefrom = 0.0f) double driftUncertaintyNanosPerSecond)407     public void setDriftUncertaintyNanosPerSecond(
408             @FloatRange(from = 0.0f) double driftUncertaintyNanosPerSecond) {
409         setFlag(HAS_DRIFT_UNCERTAINTY);
410         mDriftUncertaintyNanosPerSecond = driftUncertaintyNanosPerSecond;
411     }
412 
413     /**
414      * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
415      * @hide
416      */
417     @TestApi
resetDriftUncertaintyNanosPerSecond()418     public void resetDriftUncertaintyNanosPerSecond() {
419         resetFlag(HAS_DRIFT_UNCERTAINTY);
420     }
421 
422     /**
423      * Returns {@code true} if {@link #getElapsedRealtimeNanos()} is available, {@code false}
424      * otherwise.
425      */
hasElapsedRealtimeNanos()426     public boolean hasElapsedRealtimeNanos() {
427         return isFlagSet(HAS_ELAPSED_REALTIME_NANOS);
428     }
429 
430     /**
431      * Returns the elapsed real-time of this clock since system boot, in nanoseconds.
432      *
433      * <p>The value is only available if {@link #hasElapsedRealtimeNanos()} is
434      * {@code true}.
435      */
getElapsedRealtimeNanos()436     public long getElapsedRealtimeNanos() {
437         return mElapsedRealtimeNanos;
438     }
439 
440     /**
441      * Sets the elapsed real-time of this clock since system boot, in nanoseconds.
442      * @hide
443      */
444     @TestApi
setElapsedRealtimeNanos(long elapsedRealtimeNanos)445     public void setElapsedRealtimeNanos(long elapsedRealtimeNanos) {
446         setFlag(HAS_ELAPSED_REALTIME_NANOS);
447         mElapsedRealtimeNanos = elapsedRealtimeNanos;
448     }
449 
450     /**
451      * Resets the elapsed real-time of this clock since system boot, in nanoseconds.
452      * @hide
453      */
454     @TestApi
resetElapsedRealtimeNanos()455     public void resetElapsedRealtimeNanos() {
456         resetFlag(HAS_ELAPSED_REALTIME_NANOS);
457         mElapsedRealtimeNanos = 0;
458     }
459 
460     /**
461      * Returns {@code true} if {@link #getElapsedRealtimeUncertaintyNanos()} is available, {@code
462      * false} otherwise.
463      */
hasElapsedRealtimeUncertaintyNanos()464     public boolean hasElapsedRealtimeUncertaintyNanos() {
465         return isFlagSet(HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS);
466     }
467 
468     /**
469      * Gets the estimate of the relative precision of the alignment of the
470      * {@link #getElapsedRealtimeNanos()} timestamp, with the reported measurements in
471      * nanoseconds (68% confidence).
472      *
473      * <p>The value is only available if {@link #hasElapsedRealtimeUncertaintyNanos()} is
474      * {@code true}.
475      */
476     @FloatRange(from = 0.0f)
getElapsedRealtimeUncertaintyNanos()477     public double getElapsedRealtimeUncertaintyNanos() {
478         return mElapsedRealtimeUncertaintyNanos;
479     }
480 
481     /**
482      * Sets the estimate of the relative precision of the alignment of the
483      * {@link #getElapsedRealtimeNanos()} timestamp, with the reported measurements in
484      * nanoseconds (68% confidence).
485      * @hide
486      */
487     @TestApi
setElapsedRealtimeUncertaintyNanos( @loatRangefrom = 0.0f) double elapsedRealtimeUncertaintyNanos)488     public void setElapsedRealtimeUncertaintyNanos(
489             @FloatRange(from = 0.0f) double elapsedRealtimeUncertaintyNanos) {
490         setFlag(HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS);
491         mElapsedRealtimeUncertaintyNanos = elapsedRealtimeUncertaintyNanos;
492     }
493 
494     /**
495      * Resets the estimate of the relative precision of the alignment of the
496      * {@link #getElapsedRealtimeNanos()} timestamp, with the reported measurements in
497      * nanoseconds (68% confidence).
498      * @hide
499      */
500     @TestApi
resetElapsedRealtimeUncertaintyNanos()501     public void resetElapsedRealtimeUncertaintyNanos() {
502         resetFlag(HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS);
503     }
504 
505     /**
506      * Returns {@code true} if {@link #getReferenceConstellationTypeForIsb()} is available,
507      * {@code false} otherwise.
508      */
hasReferenceConstellationTypeForIsb()509     public boolean hasReferenceConstellationTypeForIsb() {
510         return isFlagSet(HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB);
511     }
512 
513     /**
514      * Returns the reference constellation type for inter-signal bias.
515      *
516      * <p>The value is only available if {@link #hasReferenceConstellationTypeForIsb()} is
517      * {@code true}.
518      *
519      * <p>The return value is one of those constants with {@code CONSTELLATION_} prefix in
520      * {@link GnssStatus}.
521      */
522     @GnssStatus.ConstellationType
getReferenceConstellationTypeForIsb()523     public int getReferenceConstellationTypeForIsb() {
524         return mReferenceConstellationTypeForIsb;
525     }
526 
527     /**
528      * Sets the reference constellation type for inter-signal bias.
529      * @hide
530      */
531     @TestApi
setReferenceConstellationTypeForIsb(@nssStatus.ConstellationType int value)532     public void setReferenceConstellationTypeForIsb(@GnssStatus.ConstellationType int value) {
533         setFlag(HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB);
534         mReferenceConstellationTypeForIsb = value;
535     }
536 
537     /**
538      * Resets the reference constellation type for inter-signal bias.
539      * @hide
540      */
541     @TestApi
resetReferenceConstellationTypeForIsb()542     public void resetReferenceConstellationTypeForIsb() {
543         resetFlag(HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB);
544         mReferenceConstellationTypeForIsb = GnssStatus.CONSTELLATION_UNKNOWN;
545     }
546 
547     /**
548      * Returns {@code true} if {@link #getReferenceCarrierFrequencyHzForIsb()} is available, {@code
549      * false} otherwise.
550      */
hasReferenceCarrierFrequencyHzForIsb()551     public boolean hasReferenceCarrierFrequencyHzForIsb() {
552         return isFlagSet(HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB);
553     }
554 
555     /**
556      * Returns the reference carrier frequency in Hz for inter-signal bias.
557      *
558      * <p>The value is only available if {@link #hasReferenceCarrierFrequencyHzForIsb()} is
559      * {@code true}.
560      */
561     @FloatRange(from = 0.0)
getReferenceCarrierFrequencyHzForIsb()562     public double getReferenceCarrierFrequencyHzForIsb() {
563         return mReferenceCarrierFrequencyHzForIsb;
564     }
565 
566     /**
567      * Sets the reference carrier frequency in Hz for inter-signal bias.
568      * @hide
569      */
570     @TestApi
setReferenceCarrierFrequencyHzForIsb(@loatRangefrom = 0.0) double value)571     public void setReferenceCarrierFrequencyHzForIsb(@FloatRange(from = 0.0) double value) {
572         setFlag(HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB);
573         mReferenceCarrierFrequencyHzForIsb = value;
574     }
575 
576     /**
577      * Resets the reference carrier frequency in Hz for inter-signal bias.
578      * @hide
579      */
580     @TestApi
resetReferenceCarrierFrequencyHzForIsb()581     public void resetReferenceCarrierFrequencyHzForIsb() {
582         resetFlag(HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB);
583     }
584 
585     /**
586      * Returns {@code true} if {@link #getReferenceCodeTypeForIsb()} is available, {@code
587      * false} otherwise.
588      */
hasReferenceCodeTypeForIsb()589     public boolean hasReferenceCodeTypeForIsb() {
590         return isFlagSet(HAS_REFERENCE_CODE_TYPE_FOR_ISB);
591     }
592 
593     /**
594      * Returns the reference code type for inter-signal bias.
595      *
596      * <p>The value is only available if {@link #hasReferenceCodeTypeForIsb()} is
597      * {@code true}.
598      *
599      * <p>The return value is one of those constants defined in
600      * {@link GnssMeasurement#getCodeType()}.
601      */
602     @NonNull
getReferenceCodeTypeForIsb()603     public String getReferenceCodeTypeForIsb() {
604         return mReferenceCodeTypeForIsb;
605     }
606 
607     /**
608      * Sets the reference code type for inter-signal bias.
609      * @hide
610      */
611     @TestApi
setReferenceCodeTypeForIsb(@onNull String codeType)612     public void setReferenceCodeTypeForIsb(@NonNull String codeType) {
613         setFlag(HAS_REFERENCE_CODE_TYPE_FOR_ISB);
614         mReferenceCodeTypeForIsb = codeType;
615     }
616 
617     /**
618      * Resets the reference code type for inter-signal bias.
619      * @hide
620      */
621     @TestApi
resetReferenceCodeTypeForIsb()622     public void resetReferenceCodeTypeForIsb() {
623         resetFlag(HAS_REFERENCE_CODE_TYPE_FOR_ISB);
624         mReferenceCodeTypeForIsb = "UNKNOWN";
625     }
626 
627     /**
628      * Gets count of hardware clock discontinuities.
629      *
630      * <p>When this value stays the same, vs. a value in a previously reported {@link GnssClock}, it
631      * can be safely assumed that the {@code TimeNanos} value has been derived from a clock that has
632      * been running continuously - e.g. a single continuously powered crystal oscillator, and thus
633      * the {@code (FullBiasNanos + BiasNanos)} offset can be modelled with traditional clock bias
634      * &amp; drift models.
635      *
636      * <p>Each time this value changes, vs. the value in a previously reported {@link GnssClock},
637      * that suggests the hardware clock may have experienced a discontinuity (e.g. a power cycle or
638      * other anomaly), so that any assumptions about modelling a smoothly changing
639      * {@code (FullBiasNanos + BiasNanos)} offset, and a smoothly growing {@code (TimeNanos)}
640      * between this and the previously reported {@code GnssClock}, should be reset.
641      */
getHardwareClockDiscontinuityCount()642     public int getHardwareClockDiscontinuityCount() {
643         return mHardwareClockDiscontinuityCount;
644     }
645 
646     /**
647      * Sets count of last hardware clock discontinuity.
648      * @hide
649      */
650     @TestApi
setHardwareClockDiscontinuityCount(int value)651     public void setHardwareClockDiscontinuityCount(int value) {
652         mHardwareClockDiscontinuityCount = value;
653     }
654 
655     public static final @android.annotation.NonNull Creator<GnssClock> CREATOR = new Creator<GnssClock>() {
656         @Override
657         public GnssClock createFromParcel(Parcel parcel) {
658             GnssClock gpsClock = new GnssClock();
659 
660             gpsClock.mFlags = parcel.readInt();
661             gpsClock.mLeapSecond = parcel.readInt();
662             gpsClock.mTimeNanos = parcel.readLong();
663             gpsClock.mTimeUncertaintyNanos = parcel.readDouble();
664             gpsClock.mFullBiasNanos = parcel.readLong();
665             gpsClock.mBiasNanos = parcel.readDouble();
666             gpsClock.mBiasUncertaintyNanos = parcel.readDouble();
667             gpsClock.mDriftNanosPerSecond = parcel.readDouble();
668             gpsClock.mDriftUncertaintyNanosPerSecond = parcel.readDouble();
669             gpsClock.mHardwareClockDiscontinuityCount = parcel.readInt();
670             gpsClock.mElapsedRealtimeNanos = parcel.readLong();
671             gpsClock.mElapsedRealtimeUncertaintyNanos = parcel.readDouble();
672             gpsClock.mReferenceConstellationTypeForIsb = parcel.readInt();
673             gpsClock.mReferenceCarrierFrequencyHzForIsb = parcel.readDouble();
674             gpsClock.mReferenceCodeTypeForIsb = parcel.readString();
675 
676             return gpsClock;
677         }
678 
679         @Override
680         public GnssClock[] newArray(int size) {
681             return new GnssClock[size];
682         }
683     };
684 
685     @Override
writeToParcel(Parcel parcel, int flags)686     public void writeToParcel(Parcel parcel, int flags) {
687         parcel.writeInt(mFlags);
688         parcel.writeInt(mLeapSecond);
689         parcel.writeLong(mTimeNanos);
690         parcel.writeDouble(mTimeUncertaintyNanos);
691         parcel.writeLong(mFullBiasNanos);
692         parcel.writeDouble(mBiasNanos);
693         parcel.writeDouble(mBiasUncertaintyNanos);
694         parcel.writeDouble(mDriftNanosPerSecond);
695         parcel.writeDouble(mDriftUncertaintyNanosPerSecond);
696         parcel.writeInt(mHardwareClockDiscontinuityCount);
697         parcel.writeLong(mElapsedRealtimeNanos);
698         parcel.writeDouble(mElapsedRealtimeUncertaintyNanos);
699         parcel.writeInt(mReferenceConstellationTypeForIsb);
700         parcel.writeDouble(mReferenceCarrierFrequencyHzForIsb);
701         parcel.writeString(mReferenceCodeTypeForIsb);
702     }
703 
704     @Override
describeContents()705     public int describeContents() {
706         return 0;
707     }
708 
709     @Override
toString()710     public String toString() {
711         final String format = "   %-15s = %s\n";
712         final String formatWithUncertainty = "   %-15s = %-25s   %-26s = %s\n";
713         StringBuilder builder = new StringBuilder("GnssClock:\n");
714 
715         if (hasLeapSecond()) {
716             builder.append(String.format(format, "LeapSecond", mLeapSecond));
717         }
718 
719         builder.append(String.format(
720                 formatWithUncertainty,
721                 "TimeNanos",
722                 mTimeNanos,
723                 "TimeUncertaintyNanos",
724                 hasTimeUncertaintyNanos() ? mTimeUncertaintyNanos : null));
725 
726         if (hasFullBiasNanos()) {
727             builder.append(String.format(format, "FullBiasNanos", mFullBiasNanos));
728         }
729 
730         if (hasBiasNanos() || hasBiasUncertaintyNanos()) {
731             builder.append(String.format(
732                     formatWithUncertainty,
733                     "BiasNanos",
734                     hasBiasNanos() ? mBiasNanos : null,
735                     "BiasUncertaintyNanos",
736                     hasBiasUncertaintyNanos() ? mBiasUncertaintyNanos : null));
737         }
738 
739         if (hasDriftNanosPerSecond() || hasDriftUncertaintyNanosPerSecond()) {
740             builder.append(String.format(
741                     formatWithUncertainty,
742                     "DriftNanosPerSecond",
743                     hasDriftNanosPerSecond() ? mDriftNanosPerSecond : null,
744                     "DriftUncertaintyNanosPerSecond",
745                     hasDriftUncertaintyNanosPerSecond() ? mDriftUncertaintyNanosPerSecond : null));
746         }
747 
748         builder.append(String.format(
749                 format,
750                 "HardwareClockDiscontinuityCount",
751                 mHardwareClockDiscontinuityCount));
752 
753         if (hasElapsedRealtimeNanos() || hasElapsedRealtimeUncertaintyNanos()) {
754             builder.append(String.format(
755                     formatWithUncertainty,
756                     "ElapsedRealtimeNanos",
757                     hasElapsedRealtimeNanos() ? mElapsedRealtimeNanos : null,
758                     "ElapsedRealtimeUncertaintyNanos",
759                     hasElapsedRealtimeUncertaintyNanos() ? mElapsedRealtimeUncertaintyNanos
760                             : null));
761         }
762 
763         if (hasReferenceConstellationTypeForIsb()) {
764             builder.append(String.format(format, "ReferenceConstellationTypeForIsb",
765                     mReferenceConstellationTypeForIsb));
766         }
767 
768         if (hasReferenceCarrierFrequencyHzForIsb()) {
769             builder.append(String.format(format, "ReferenceCarrierFrequencyHzForIsb",
770                     mReferenceCarrierFrequencyHzForIsb));
771         }
772 
773         if (hasReferenceCodeTypeForIsb()) {
774             builder.append(
775                     String.format(format, "ReferenceCodeTypeForIsb", mReferenceCodeTypeForIsb));
776         }
777 
778         return builder.toString();
779     }
780 
initialize()781     private void initialize() {
782         mFlags = HAS_NO_FLAGS;
783         resetLeapSecond();
784         setTimeNanos(Long.MIN_VALUE);
785         resetTimeUncertaintyNanos();
786         resetFullBiasNanos();
787         resetBiasNanos();
788         resetBiasUncertaintyNanos();
789         resetDriftNanosPerSecond();
790         resetDriftUncertaintyNanosPerSecond();
791         setHardwareClockDiscontinuityCount(Integer.MIN_VALUE);
792         resetElapsedRealtimeNanos();
793         resetElapsedRealtimeUncertaintyNanos();
794         resetReferenceConstellationTypeForIsb();
795         resetReferenceCarrierFrequencyHzForIsb();
796         resetReferenceCodeTypeForIsb();
797     }
798 
setFlag(int flag)799     private void setFlag(int flag) {
800         mFlags |= flag;
801     }
802 
resetFlag(int flag)803     private void resetFlag(int flag) {
804         mFlags &= ~flag;
805     }
806 
isFlagSet(int flag)807     private boolean isFlagSet(int flag) {
808         return (mFlags & flag) == flag;
809     }
810 }
811