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 * & 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