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