GnssClock.java revision 76a620f0482ba54a4921c7c7e7eeb8ea87c12d3e
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
17package android.location;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21
22/**
23 * A class containing a GPS clock timestamp.
24 * It represents a measurement of the GPS receiver's clock.
25 */
26public final class GnssClock implements Parcelable {
27    // The following enumerations must be in sync with the values declared in gps.h
28
29    private static final int HAS_NO_FLAGS = 0;
30    private static final int HAS_LEAP_SECOND = (1<<0);
31    private static final int HAS_TIME_UNCERTAINTY = (1<<1);
32    private static final int HAS_FULL_BIAS = (1<<2);
33    private static final int HAS_BIAS = (1<<3);
34    private static final int HAS_BIAS_UNCERTAINTY = (1<<4);
35    private static final int HAS_DRIFT = (1<<5);
36    private static final int HAS_DRIFT_UNCERTAINTY = (1<<6);
37
38    // End enumerations in sync with gps.h
39
40    private int mFlags;
41    private int mLeapSecond;
42    private long mTimeNanos;
43    private double mTimeUncertaintyNanos;
44    private long mFullBiasNanos;
45    private double mBiasNanos;
46    private double mBiasUncertaintyNanos;
47    private double mDriftNanosPerSecond;
48    private double mDriftUncertaintyNanosPerSecond;
49    private int mHardwareClockDiscontinuityCount;
50
51    GnssClock() {
52        initialize();
53    }
54
55    /**
56     * Sets all contents to the values stored in the provided object.
57     */
58    public void set(GnssClock clock) {
59        mFlags = clock.mFlags;
60        mLeapSecond = clock.mLeapSecond;
61        mTimeNanos = clock.mTimeNanos;
62        mTimeUncertaintyNanos = clock.mTimeUncertaintyNanos;
63        mFullBiasNanos = clock.mFullBiasNanos;
64        mBiasNanos = clock.mBiasNanos;
65        mBiasUncertaintyNanos = clock.mBiasUncertaintyNanos;
66        mDriftNanosPerSecond = clock.mDriftNanosPerSecond;
67        mDriftUncertaintyNanosPerSecond = clock.mDriftUncertaintyNanosPerSecond;
68        mHardwareClockDiscontinuityCount = clock.mHardwareClockDiscontinuityCount;
69    }
70
71    /**
72     * Resets all the contents to its original state.
73     */
74    public void reset() {
75        initialize();
76    }
77
78    /**
79     * Returns true if {@link #getLeapSecond()} is available, false otherwise.
80     */
81    public boolean hasLeapSecond() {
82        return isFlagSet(HAS_LEAP_SECOND);
83    }
84
85    /**
86     * Gets the leap second associated with the clock's time.
87     * The sign of the value is defined by the following equation:
88     *      utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000
89     *
90     * The value is only available if {@link #hasLeapSecond()} is true.
91     */
92    public int getLeapSecond() {
93        return mLeapSecond;
94    }
95
96    /**
97     * Sets the leap second associated with the clock's time.
98     */
99    public void setLeapSecond(int leapSecond) {
100        setFlag(HAS_LEAP_SECOND);
101        mLeapSecond = leapSecond;
102    }
103
104    /**
105     * Resets the leap second associated with the clock's time.
106     */
107    public void resetLeapSecond() {
108        resetFlag(HAS_LEAP_SECOND);
109        mLeapSecond = Integer.MIN_VALUE;
110    }
111
112    /**
113     * Gets the GNSS receiver internal clock value in nanoseconds.
114     *
115     * For 'local hardware clock' this value is expected to be monotonically increasing during the
116     * reporting session. The real GPS time can be derived by compensating
117     * {@link #getFullBiasNanos()} (when it is available) from this value.
118     *
119     * For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS
120     * receiver can achieve. {@link #getTimeUncertaintyNanos()} should be available when GPS time is
121     * specified.
122     *
123     * Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}.
124     * The reported time includes {@link #getTimeUncertaintyNanos()}.
125     */
126    public long getTimeNanos() {
127        return mTimeNanos;
128    }
129
130    /**
131     * Sets the GNSS receiver internal clock in nanoseconds.
132     */
133    public void setTimeNanos(long timeNanos) {
134        mTimeNanos = timeNanos;
135    }
136
137    /**
138     * Returns true if {@link #getTimeUncertaintyNanos()} is available, false otherwise.
139     */
140    public boolean hasTimeUncertaintyNanos() {
141        return isFlagSet(HAS_TIME_UNCERTAINTY);
142    }
143
144    /**
145     * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
146     * The uncertainty is represented as an absolute (single sided) value.
147     *
148     * The value is only available if {@link #hasTimeUncertaintyNanos()} is true.
149     */
150    public double getTimeUncertaintyNanos() {
151        return mTimeUncertaintyNanos;
152    }
153
154    /**
155     * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
156     */
157    public void setTimeUncertaintyNanos(double timeUncertaintyNanos) {
158        setFlag(HAS_TIME_UNCERTAINTY);
159        mTimeUncertaintyNanos = timeUncertaintyNanos;
160    }
161
162    /**
163     * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
164     */
165    public void resetTimeUncertaintyNanos() {
166        resetFlag(HAS_TIME_UNCERTAINTY);
167        mTimeUncertaintyNanos = Double.NaN;
168    }
169
170    /**
171     * Returns true if {@link #getFullBiasNanos()} is available, false otherwise.
172     */
173    public boolean hasFullBiasNanos() {
174        return isFlagSet(HAS_FULL_BIAS);
175    }
176
177    /**
178     * Gets the difference between hardware clock ({@link #getTimeNanos()}) inside GPS receiver and
179     * the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
180     *
181     * This value is available if the receiver has estimated GPS time. If the computed time is for a
182     * non-GPS constellation, the time offset of that constellation to GPS has to be applied to fill
183     * this value. The value contains the 'bias uncertainty' {@link #getBiasUncertaintyNanos()} in
184     * it, and it should be used for quality check. The value is only available if
185     * {@link #hasFullBiasNanos()} is true.
186     *
187     * The sign of the value is defined by the following equation:
188     *      local estimate of GPS time = time_ns + (full_bias_ns + bias_ns)
189     */
190    public long getFullBiasNanos() {
191        return mFullBiasNanos;
192    }
193
194    /**
195     * Sets the full bias in nanoseconds.
196     */
197    public void setFullBiasNanos(long value) {
198        setFlag(HAS_FULL_BIAS);
199        mFullBiasNanos = value;
200    }
201
202    /**
203     * Resets the full bias in nanoseconds.
204     */
205    public void resetFullBiasNanos() {
206        resetFlag(HAS_FULL_BIAS);
207        mFullBiasNanos = Long.MIN_VALUE;
208    }
209
210    /**
211     * Returns true if {@link #getBiasNanos()} is available, false otherwise.
212     */
213    public boolean hasBiasNanos() {
214        return isFlagSet(HAS_BIAS);
215    }
216
217    /**
218     * Gets the clock's sub-nanosecond bias.
219     * The reported bias includes {@link #getBiasUncertaintyNanos()}.
220     *
221     * The value is only available if {@link #hasBiasNanos()} is true.
222     */
223    public double getBiasNanos() {
224        return mBiasNanos;
225    }
226
227    /**
228     * Sets the sub-nanosecond bias.
229     */
230    public void setBiasNanos(double biasNanos) {
231        setFlag(HAS_BIAS);
232        mBiasNanos = biasNanos;
233    }
234
235    /**
236     * Resets the clock's Bias in nanoseconds.
237     */
238    public void resetBiasNanos() {
239        resetFlag(HAS_BIAS);
240        mBiasNanos = Double.NaN;
241    }
242
243    /**
244     * Returns true if {@link #getBiasUncertaintyNanos()} is available, false otherwise.
245     */
246    public boolean hasBiasUncertaintyNanos() {
247        return isFlagSet(HAS_BIAS_UNCERTAINTY);
248    }
249
250    /**
251     * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
252     *
253     * The value is only available if {@link #hasBiasUncertaintyNanos()} is true.
254     */
255    public double getBiasUncertaintyNanos() {
256        return mBiasUncertaintyNanos;
257    }
258
259    /**
260     * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
261     */
262    public void setBiasUncertaintyNanos(double biasUncertaintyNanos) {
263        setFlag(HAS_BIAS_UNCERTAINTY);
264        mBiasUncertaintyNanos = biasUncertaintyNanos;
265    }
266
267    /**
268     * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
269     */
270    public void resetBiasUncertaintyNanos() {
271        resetFlag(HAS_BIAS_UNCERTAINTY);
272        mBiasUncertaintyNanos = Double.NaN;
273    }
274
275    /**
276     * Returns true if {@link #getDriftNanosPerSecond()} is available, false otherwise.
277     */
278    public boolean hasDriftNanosPerSecond() {
279        return isFlagSet(HAS_DRIFT);
280    }
281
282    /**
283     * Gets the clock's Drift in nanoseconds per second.
284     * A positive value indicates that the frequency is higher than the nominal frequency.
285     * The reported drift includes {@link #getDriftUncertaintyNanosPerSecond()}.
286     *
287     * The value is only available if {@link #hasDriftNanosPerSecond()} is true.
288     */
289    public double getDriftNanosPerSecond() {
290        return mDriftNanosPerSecond;
291    }
292
293    /**
294     * Sets the clock's Drift in nanoseconds per second.
295     */
296    public void setDriftNanosPerSecond(double driftNanosPerSecond) {
297        setFlag(HAS_DRIFT);
298        mDriftNanosPerSecond = driftNanosPerSecond;
299    }
300
301    /**
302     * Resets the clock's Drift in nanoseconds per second.
303     */
304    public void resetDriftNanosPerSecond() {
305        resetFlag(HAS_DRIFT);
306        mDriftNanosPerSecond = Double.NaN;
307    }
308
309    /**
310     * Returns true if {@link #getDriftUncertaintyNanosPerSecond()} is available, false otherwise.
311     */
312    public boolean hasDriftUncertaintyNanosPerSecond() {
313        return isFlagSet(HAS_DRIFT_UNCERTAINTY);
314    }
315
316    /**
317     * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
318     *
319     * The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is true.
320     */
321    public double getDriftUncertaintyNanosPerSecond() {
322        return mDriftUncertaintyNanosPerSecond;
323    }
324
325    /**
326     * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
327     */
328    public void setDriftUncertaintyNanosPerSecond(double driftUncertaintyNanosPerSecond) {
329        setFlag(HAS_DRIFT_UNCERTAINTY);
330        mDriftUncertaintyNanosPerSecond = driftUncertaintyNanosPerSecond;
331    }
332
333    /**
334     * Gets count of last hardware clock discontinuity.
335     */
336    public int getHardwareClockDiscontinuityCount() {
337        return mHardwareClockDiscontinuityCount;
338    }
339
340    /**
341     * Sets count of last hardware clock discontinuity.
342     */
343    public void setHardwareClockDiscontinuityCount(int value) {
344        mHardwareClockDiscontinuityCount = value;
345    }
346
347    /**
348     * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
349     */
350    public void resetDriftUncertaintyNanosPerSecond() {
351        resetFlag(HAS_DRIFT_UNCERTAINTY);
352        mDriftUncertaintyNanosPerSecond = Double.NaN;
353    }
354
355    public static final Creator<GnssClock> CREATOR = new Creator<GnssClock>() {
356        @Override
357        public GnssClock createFromParcel(Parcel parcel) {
358            GnssClock gpsClock = new GnssClock();
359
360            gpsClock.mFlags = parcel.readInt();
361            gpsClock.mLeapSecond = parcel.readInt();
362            gpsClock.mTimeNanos = parcel.readLong();
363            gpsClock.mTimeUncertaintyNanos = parcel.readDouble();
364            gpsClock.mFullBiasNanos = parcel.readLong();
365            gpsClock.mBiasNanos = parcel.readDouble();
366            gpsClock.mBiasUncertaintyNanos = parcel.readDouble();
367            gpsClock.mDriftNanosPerSecond = parcel.readDouble();
368            gpsClock.mDriftUncertaintyNanosPerSecond = parcel.readDouble();
369            gpsClock.mHardwareClockDiscontinuityCount = parcel.readInt();
370
371            return gpsClock;
372        }
373
374        @Override
375        public GnssClock[] newArray(int size) {
376            return new GnssClock[size];
377        }
378    };
379
380    @Override
381    public void writeToParcel(Parcel parcel, int flags) {
382        parcel.writeInt(mFlags);
383        parcel.writeInt(mLeapSecond);
384        parcel.writeLong(mTimeNanos);
385        parcel.writeDouble(mTimeUncertaintyNanos);
386        parcel.writeLong(mFullBiasNanos);
387        parcel.writeDouble(mBiasNanos);
388        parcel.writeDouble(mBiasUncertaintyNanos);
389        parcel.writeDouble(mDriftNanosPerSecond);
390        parcel.writeDouble(mDriftUncertaintyNanosPerSecond);
391        parcel.writeInt(mHardwareClockDiscontinuityCount);
392    }
393
394    @Override
395    public int describeContents() {
396        return 0;
397    }
398
399    @Override
400    public String toString() {
401        final String format = "   %-15s = %s\n";
402        final String formatWithUncertainty = "   %-15s = %-25s   %-26s = %s\n";
403        StringBuilder builder = new StringBuilder("GnssClock:\n");
404
405        builder.append(String.format(format, "LeapSecond", hasLeapSecond() ? mLeapSecond : null));
406
407        builder.append(String.format(
408                formatWithUncertainty,
409                "TimeNanos",
410                mTimeNanos,
411                "TimeUncertaintyNanos",
412                hasTimeUncertaintyNanos() ? mTimeUncertaintyNanos : null));
413
414        builder.append(String.format(
415                format,
416                "FullBiasNanos",
417                hasFullBiasNanos() ? mFullBiasNanos : null));
418
419        builder.append(String.format(
420                formatWithUncertainty,
421                "BiasNanos",
422                hasBiasNanos() ? mBiasNanos : null,
423                "BiasUncertaintyNanos",
424                hasBiasUncertaintyNanos() ? mBiasUncertaintyNanos : null));
425
426        builder.append(String.format(
427                formatWithUncertainty,
428                "DriftNanosPerSecond",
429                hasDriftNanosPerSecond() ? mDriftNanosPerSecond : null,
430                "DriftUncertaintyNanosPerSecond",
431                hasDriftUncertaintyNanosPerSecond() ? mDriftUncertaintyNanosPerSecond : null));
432
433        return builder.toString();
434    }
435
436    private void initialize() {
437        mFlags = HAS_NO_FLAGS;
438        resetLeapSecond();
439        setTimeNanos(Long.MIN_VALUE);
440        resetTimeUncertaintyNanos();
441        resetFullBiasNanos();
442        resetBiasNanos();
443        resetBiasUncertaintyNanos();
444        resetDriftNanosPerSecond();
445        resetDriftUncertaintyNanosPerSecond();
446        setHardwareClockDiscontinuityCount(Integer.MIN_VALUE);
447    }
448
449    private void setFlag(int flag) {
450        mFlags |= flag;
451    }
452
453    private void resetFlag(int flag) {
454        mFlags &= ~flag;
455    }
456
457    private boolean isFlagSet(int flag) {
458        return (mFlags & flag) == flag;
459    }
460}
461