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