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