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.NonNull;
20 import android.annotation.SystemApi;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 
24 /**
25  * A class containing a GPS clock timestamp.
26  * It represents a measurement of the GPS receiver's clock.
27  *
28  * @deprecated use {@link GnssClock} instead.
29  *
30  * @hide
31  */
32 @Deprecated
33 @SystemApi
34 public class GpsClock implements Parcelable {
35 
36     // The following enumerations must be in sync with the values declared in gps.h
37 
38     /**
39      * The type of the time stored is not available or it is unknown.
40      */
41     public static final byte TYPE_UNKNOWN = 0;
42 
43     /**
44      * The source of the time value reported by this class is the 'Local Hardware Clock'.
45      */
46     public static final byte TYPE_LOCAL_HW_TIME = 1;
47 
48     /**
49      * The source of the time value reported by this class is the 'GPS time' derived from
50      * satellites (epoch = Jan 6, 1980).
51      */
52     public static final byte TYPE_GPS_TIME = 2;
53 
54     private static final short HAS_NO_FLAGS = 0;
55     private static final short HAS_LEAP_SECOND = (1<<0);
56     private static final short HAS_TIME_UNCERTAINTY = (1<<1);
57     private static final short HAS_FULL_BIAS = (1<<2);
58     private static final short HAS_BIAS = (1<<3);
59     private static final short HAS_BIAS_UNCERTAINTY = (1<<4);
60     private static final short HAS_DRIFT = (1<<5);
61     private static final short HAS_DRIFT_UNCERTAINTY = (1<<6);
62 
63     // End enumerations in sync with gps.h
64 
65     private short mFlags;
66     private short mLeapSecond;
67     private byte mType;
68     private long mTimeInNs;
69     private double mTimeUncertaintyInNs;
70     private long mFullBiasInNs;
71     private double mBiasInNs;
72     private double mBiasUncertaintyInNs;
73     private double mDriftInNsPerSec;
74     private double mDriftUncertaintyInNsPerSec;
75 
GpsClock()76     GpsClock() {
77         initialize();
78     }
79 
80     /**
81      * Sets all contents to the values stored in the provided object.
82      */
set(GpsClock clock)83     public void set(GpsClock clock) {
84         mFlags = clock.mFlags;
85         mLeapSecond = clock.mLeapSecond;
86         mType = clock.mType;
87         mTimeInNs = clock.mTimeInNs;
88         mTimeUncertaintyInNs = clock.mTimeUncertaintyInNs;
89         mFullBiasInNs = clock.mFullBiasInNs;
90         mBiasInNs = clock.mBiasInNs;
91         mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs;
92         mDriftInNsPerSec = clock.mDriftInNsPerSec;
93         mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec;
94     }
95 
96     /**
97      * Resets all the contents to its original state.
98      */
reset()99     public void reset() {
100         initialize();
101     }
102 
103     /**
104      * Gets the type of time reported by {@link #getTimeInNs()}.
105      */
getType()106     public byte getType() {
107         return mType;
108     }
109 
110     /**
111      * Sets the type of time reported.
112      */
setType(byte value)113     public void setType(byte value) {
114         mType = value;
115     }
116 
117     /**
118      * Gets a string representation of the 'type'.
119      * For internal and logging use only.
120      */
getTypeString()121     private String getTypeString() {
122         switch (mType) {
123             case TYPE_UNKNOWN:
124                 return "Unknown";
125             case TYPE_GPS_TIME:
126                 return "GpsTime";
127             case TYPE_LOCAL_HW_TIME:
128                 return "LocalHwClock";
129             default:
130                 return "<Invalid:" + mType + ">";
131         }
132     }
133 
134     /**
135      * Returns true if {@link #getLeapSecond()} is available, false otherwise.
136      */
hasLeapSecond()137     public boolean hasLeapSecond() {
138         return isFlagSet(HAS_LEAP_SECOND);
139     }
140 
141     /**
142      * Gets the leap second associated with the clock's time.
143      * The sign of the value is defined by the following equation:
144      *      utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000
145      *
146      * The value is only available if {@link #hasLeapSecond()} is true.
147      */
getLeapSecond()148     public short getLeapSecond() {
149         return mLeapSecond;
150     }
151 
152     /**
153      * Sets the leap second associated with the clock's time.
154      */
setLeapSecond(short leapSecond)155     public void setLeapSecond(short leapSecond) {
156         setFlag(HAS_LEAP_SECOND);
157         mLeapSecond = leapSecond;
158     }
159 
160     /**
161      * Resets the leap second associated with the clock's time.
162      */
resetLeapSecond()163     public void resetLeapSecond() {
164         resetFlag(HAS_LEAP_SECOND);
165         mLeapSecond = Short.MIN_VALUE;
166     }
167 
168     /**
169      * Gets the GPS receiver internal clock value in nanoseconds.
170      * This can be either the 'local hardware clock' value ({@link #TYPE_LOCAL_HW_TIME}), or the
171      * current GPS time derived inside GPS receiver ({@link #TYPE_GPS_TIME}).
172      * {@link #getType()} defines the time reported.
173      *
174      * For 'local hardware clock' this value is expected to be monotonically increasing during the
175      * reporting session. The real GPS time can be derived by compensating
176      * {@link #getFullBiasInNs()} (when it is available) from this value.
177      *
178      * For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS
179      * receiver can achieve. {@link #getTimeUncertaintyInNs()} should be available when GPS time is
180      * specified.
181      *
182      * Sub-nanosecond accuracy can be provided by means of {@link #getBiasInNs()}.
183      * The reported time includes {@link #getTimeUncertaintyInNs()}.
184      */
getTimeInNs()185     public long getTimeInNs() {
186         return mTimeInNs;
187     }
188 
189     /**
190      * Sets the GPS receiver internal clock in nanoseconds.
191      */
setTimeInNs(long timeInNs)192     public void setTimeInNs(long timeInNs) {
193         mTimeInNs = timeInNs;
194     }
195 
196     /**
197      * Returns true if {@link #getTimeUncertaintyInNs()} is available, false otherwise.
198      */
hasTimeUncertaintyInNs()199     public boolean hasTimeUncertaintyInNs() {
200         return isFlagSet(HAS_TIME_UNCERTAINTY);
201     }
202 
203     /**
204      * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
205      * The uncertainty is represented as an absolute (single sided) value.
206      *
207      * The value is only available if {@link #hasTimeUncertaintyInNs()} is true.
208      */
getTimeUncertaintyInNs()209     public double getTimeUncertaintyInNs() {
210         return mTimeUncertaintyInNs;
211     }
212 
213     /**
214      * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
215      */
setTimeUncertaintyInNs(double timeUncertaintyInNs)216     public void setTimeUncertaintyInNs(double timeUncertaintyInNs) {
217         setFlag(HAS_TIME_UNCERTAINTY);
218         mTimeUncertaintyInNs = timeUncertaintyInNs;
219     }
220 
221     /**
222      * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
223      */
resetTimeUncertaintyInNs()224     public void resetTimeUncertaintyInNs() {
225         resetFlag(HAS_TIME_UNCERTAINTY);
226         mTimeUncertaintyInNs = Double.NaN;
227     }
228 
229     /**
230      * Returns true if {@link @getFullBiasInNs()} is available, false otherwise.
231      */
hasFullBiasInNs()232     public boolean hasFullBiasInNs() {
233         return isFlagSet(HAS_FULL_BIAS);
234     }
235 
236     /**
237      * Gets the difference between hardware clock ({@link #getTimeInNs()}) inside GPS receiver and
238      * the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
239      *
240      * This value is available if {@link #TYPE_LOCAL_HW_TIME} is set, and GPS receiver has solved
241      * the clock for GPS time.
242      * {@link #getBiasUncertaintyInNs()} should be used for quality check.
243      *
244      * The sign of the value is defined by the following equation:
245      *      true time (GPS time) = time_ns + (full_bias_ns + bias_ns)
246      *
247      * The reported full bias includes {@link #getBiasUncertaintyInNs()}.
248      * The value is onl available if {@link #hasFullBiasInNs()} is true.
249      */
getFullBiasInNs()250     public long getFullBiasInNs() {
251         return mFullBiasInNs;
252     }
253 
254     /**
255      * Sets the full bias in nanoseconds.
256      */
setFullBiasInNs(long value)257     public void setFullBiasInNs(long value) {
258         setFlag(HAS_FULL_BIAS);
259         mFullBiasInNs = value;
260     }
261 
262     /**
263      * Resets the full bias in nanoseconds.
264      */
resetFullBiasInNs()265     public void resetFullBiasInNs() {
266         resetFlag(HAS_FULL_BIAS);
267         mFullBiasInNs = Long.MIN_VALUE;
268     }
269 
270     /**
271      * Returns true if {@link #getBiasInNs()} is available, false otherwise.
272      */
hasBiasInNs()273     public boolean hasBiasInNs() {
274         return isFlagSet(HAS_BIAS);
275     }
276 
277     /**
278      * Gets the clock's sub-nanosecond bias.
279      * The reported bias includes {@link #getBiasUncertaintyInNs()}.
280      *
281      * The value is only available if {@link #hasBiasInNs()} is true.
282      */
getBiasInNs()283     public double getBiasInNs() {
284         return mBiasInNs;
285     }
286 
287     /**
288      * Sets the sub-nanosecond bias.
289      */
setBiasInNs(double biasInNs)290     public void setBiasInNs(double biasInNs) {
291         setFlag(HAS_BIAS);
292         mBiasInNs = biasInNs;
293     }
294 
295     /**
296      * Resets the clock's Bias in nanoseconds.
297      */
resetBiasInNs()298     public void resetBiasInNs() {
299         resetFlag(HAS_BIAS);
300         mBiasInNs = Double.NaN;
301     }
302 
303     /**
304      * Returns true if {@link #getBiasUncertaintyInNs()} is available, false otherwise.
305      */
hasBiasUncertaintyInNs()306     public boolean hasBiasUncertaintyInNs() {
307         return isFlagSet(HAS_BIAS_UNCERTAINTY);
308     }
309 
310     /**
311      * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
312      *
313      * The value is only available if {@link #hasBiasUncertaintyInNs()} is true.
314      */
getBiasUncertaintyInNs()315     public double getBiasUncertaintyInNs() {
316         return mBiasUncertaintyInNs;
317     }
318 
319     /**
320      * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
321      */
setBiasUncertaintyInNs(double biasUncertaintyInNs)322     public void setBiasUncertaintyInNs(double biasUncertaintyInNs) {
323         setFlag(HAS_BIAS_UNCERTAINTY);
324         mBiasUncertaintyInNs = biasUncertaintyInNs;
325     }
326 
327     /**
328      * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
329      */
resetBiasUncertaintyInNs()330     public void resetBiasUncertaintyInNs() {
331         resetFlag(HAS_BIAS_UNCERTAINTY);
332         mBiasUncertaintyInNs = Double.NaN;
333     }
334 
335     /**
336      * Returns true if {@link #getDriftInNsPerSec()} is available, false otherwise.
337      */
hasDriftInNsPerSec()338     public boolean hasDriftInNsPerSec() {
339         return isFlagSet(HAS_DRIFT);
340     }
341 
342     /**
343      * Gets the clock's Drift in nanoseconds per second.
344      * A positive value indicates that the frequency is higher than the nominal frequency.
345      * The reported drift includes {@link #getDriftUncertaintyInNsPerSec()}.
346      *
347      * The value is only available if {@link #hasDriftInNsPerSec()} is true.
348      */
getDriftInNsPerSec()349     public double getDriftInNsPerSec() {
350         return mDriftInNsPerSec;
351     }
352 
353     /**
354      * Sets the clock's Drift in nanoseconds per second.
355      */
setDriftInNsPerSec(double driftInNsPerSec)356     public void setDriftInNsPerSec(double driftInNsPerSec) {
357         setFlag(HAS_DRIFT);
358         mDriftInNsPerSec = driftInNsPerSec;
359     }
360 
361     /**
362      * Resets the clock's Drift in nanoseconds per second.
363      */
resetDriftInNsPerSec()364     public void resetDriftInNsPerSec() {
365         resetFlag(HAS_DRIFT);
366         mDriftInNsPerSec = Double.NaN;
367     }
368 
369     /**
370      * Returns true if {@link #getDriftUncertaintyInNsPerSec()} is available, false otherwise.
371      */
hasDriftUncertaintyInNsPerSec()372     public boolean hasDriftUncertaintyInNsPerSec() {
373         return isFlagSet(HAS_DRIFT_UNCERTAINTY);
374     }
375 
376     /**
377      * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
378      *
379      * The value is only available if {@link #hasDriftUncertaintyInNsPerSec()} is true.
380      */
getDriftUncertaintyInNsPerSec()381     public double getDriftUncertaintyInNsPerSec() {
382         return mDriftUncertaintyInNsPerSec;
383     }
384 
385     /**
386      * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
387      */
setDriftUncertaintyInNsPerSec(double driftUncertaintyInNsPerSec)388     public void setDriftUncertaintyInNsPerSec(double driftUncertaintyInNsPerSec) {
389         setFlag(HAS_DRIFT_UNCERTAINTY);
390         mDriftUncertaintyInNsPerSec = driftUncertaintyInNsPerSec;
391     }
392 
393     /**
394      * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
395      */
resetDriftUncertaintyInNsPerSec()396     public void resetDriftUncertaintyInNsPerSec() {
397         resetFlag(HAS_DRIFT_UNCERTAINTY);
398         mDriftUncertaintyInNsPerSec = Double.NaN;
399     }
400 
401     public static final @android.annotation.NonNull Creator<GpsClock> CREATOR = new Creator<GpsClock>() {
402         @Override
403         public GpsClock createFromParcel(Parcel parcel) {
404             GpsClock gpsClock = new GpsClock();
405 
406             gpsClock.mFlags = (short) parcel.readInt();
407             gpsClock.mLeapSecond = (short) parcel.readInt();
408             gpsClock.mType = parcel.readByte();
409             gpsClock.mTimeInNs = parcel.readLong();
410             gpsClock.mTimeUncertaintyInNs = parcel.readDouble();
411             gpsClock.mFullBiasInNs = parcel.readLong();
412             gpsClock.mBiasInNs = parcel.readDouble();
413             gpsClock.mBiasUncertaintyInNs = parcel.readDouble();
414             gpsClock.mDriftInNsPerSec = parcel.readDouble();
415             gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble();
416 
417             return gpsClock;
418         }
419 
420         @Override
421         public GpsClock[] newArray(int size) {
422             return new GpsClock[size];
423         }
424     };
425 
writeToParcel(Parcel parcel, int flags)426     public void writeToParcel(Parcel parcel, int flags) {
427         parcel.writeInt(mFlags);
428         parcel.writeInt(mLeapSecond);
429         parcel.writeByte(mType);
430         parcel.writeLong(mTimeInNs);
431         parcel.writeDouble(mTimeUncertaintyInNs);
432         parcel.writeLong(mFullBiasInNs);
433         parcel.writeDouble(mBiasInNs);
434         parcel.writeDouble(mBiasUncertaintyInNs);
435         parcel.writeDouble(mDriftInNsPerSec);
436         parcel.writeDouble(mDriftUncertaintyInNsPerSec);
437     }
438 
439     @Override
describeContents()440     public int describeContents() {
441         return 0;
442     }
443 
444     @NonNull
445     @Override
toString()446     public String toString() {
447         final String format = "   %-15s = %s\n";
448         final String formatWithUncertainty = "   %-15s = %-25s   %-26s = %s\n";
449         StringBuilder builder = new StringBuilder("GpsClock:\n");
450 
451         builder.append(String.format(format, "Type", getTypeString()));
452 
453         builder.append(String.format(format, "LeapSecond", hasLeapSecond() ? mLeapSecond : null));
454 
455         builder.append(String.format(
456                 formatWithUncertainty,
457                 "TimeInNs",
458                 mTimeInNs,
459                 "TimeUncertaintyInNs",
460                 hasTimeUncertaintyInNs() ? mTimeUncertaintyInNs : null));
461 
462         builder.append(String.format(
463                 format,
464                 "FullBiasInNs",
465                 hasFullBiasInNs() ? mFullBiasInNs : null));
466 
467         builder.append(String.format(
468                 formatWithUncertainty,
469                 "BiasInNs",
470                 hasBiasInNs() ? mBiasInNs : null,
471                 "BiasUncertaintyInNs",
472                 hasBiasUncertaintyInNs() ? mBiasUncertaintyInNs : null));
473 
474         builder.append(String.format(
475                 formatWithUncertainty,
476                 "DriftInNsPerSec",
477                 hasDriftInNsPerSec() ? mDriftInNsPerSec : null,
478                 "DriftUncertaintyInNsPerSec",
479                 hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null));
480 
481         return builder.toString();
482     }
483 
initialize()484     private void initialize() {
485         mFlags = HAS_NO_FLAGS;
486         resetLeapSecond();
487         setType(TYPE_UNKNOWN);
488         setTimeInNs(Long.MIN_VALUE);
489         resetTimeUncertaintyInNs();
490         resetFullBiasInNs();
491         resetBiasInNs();
492         resetBiasUncertaintyInNs();
493         resetDriftInNsPerSec();
494         resetDriftUncertaintyInNsPerSec();
495     }
496 
setFlag(short flag)497     private void setFlag(short flag) {
498         mFlags |= flag;
499     }
500 
resetFlag(short flag)501     private void resetFlag(short flag) {
502         mFlags &= ~flag;
503     }
504 
isFlagSet(short flag)505     private boolean isFlagSet(short flag) {
506         return (mFlags & flag) == flag;
507     }
508 }
509