/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package android.location; import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; /** * A class containing a GPS clock timestamp. * *
It represents a measurement of the GPS receiver's clock. */ public final class GnssClock implements Parcelable { // The following enumerations must be in sync with the values declared in gps.h private static final int HAS_NO_FLAGS = 0; private static final int HAS_LEAP_SECOND = (1<<0); private static final int HAS_TIME_UNCERTAINTY = (1<<1); private static final int HAS_FULL_BIAS = (1<<2); private static final int HAS_BIAS = (1<<3); private static final int HAS_BIAS_UNCERTAINTY = (1<<4); private static final int HAS_DRIFT = (1<<5); private static final int HAS_DRIFT_UNCERTAINTY = (1<<6); // End enumerations in sync with gps.h private int mFlags; private int mLeapSecond; private long mTimeNanos; private double mTimeUncertaintyNanos; private long mFullBiasNanos; private double mBiasNanos; private double mBiasUncertaintyNanos; private double mDriftNanosPerSecond; private double mDriftUncertaintyNanosPerSecond; private int mHardwareClockDiscontinuityCount; /** * @hide */ @TestApi public GnssClock() { initialize(); } /** * Sets all contents to the values stored in the provided object. * @hide */ @TestApi public void set(GnssClock clock) { mFlags = clock.mFlags; mLeapSecond = clock.mLeapSecond; mTimeNanos = clock.mTimeNanos; mTimeUncertaintyNanos = clock.mTimeUncertaintyNanos; mFullBiasNanos = clock.mFullBiasNanos; mBiasNanos = clock.mBiasNanos; mBiasUncertaintyNanos = clock.mBiasUncertaintyNanos; mDriftNanosPerSecond = clock.mDriftNanosPerSecond; mDriftUncertaintyNanosPerSecond = clock.mDriftUncertaintyNanosPerSecond; mHardwareClockDiscontinuityCount = clock.mHardwareClockDiscontinuityCount; } /** * Resets all the contents to its original state. * @hide */ @TestApi public void reset() { initialize(); } /** * Returns {@code true} if {@link #getLeapSecond()} is available, {@code false} otherwise. */ public boolean hasLeapSecond() { return isFlagSet(HAS_LEAP_SECOND); } /** * Gets the leap second associated with the clock's time. * *
The sign of the value is defined by the following equation: *
* UtcTimeNanos = TimeNanos - (FullBiasNanos + BiasNanos) - LeapSecond * 1,000,000,000* *
The value is only available if {@link #hasLeapSecond()} is {@code true}. */ public int getLeapSecond() { return mLeapSecond; } /** * Sets the leap second associated with the clock's time. * @hide */ @TestApi public void setLeapSecond(int leapSecond) { setFlag(HAS_LEAP_SECOND); mLeapSecond = leapSecond; } /** * Resets the leap second associated with the clock's time. * @hide */ @TestApi public void resetLeapSecond() { resetFlag(HAS_LEAP_SECOND); mLeapSecond = Integer.MIN_VALUE; } /** * Gets the GNSS receiver internal hardware clock value in nanoseconds. * *
This value is expected to be monotonically increasing while the hardware clock remains * powered on. For the case of a hardware clock that is not continuously on, see the * {@link #getHardwareClockDiscontinuityCount} field. The GPS time can be derived by subtracting * the sum of {@link #getFullBiasNanos()} and {@link #getBiasNanos()} (when they are available) * from this value. Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}. * *
The error estimate for this value (if applicable) is {@link #getTimeUncertaintyNanos()}. */ public long getTimeNanos() { return mTimeNanos; } /** * Sets the GNSS receiver internal clock in nanoseconds. * @hide */ @TestApi public void setTimeNanos(long timeNanos) { mTimeNanos = timeNanos; } /** * Returns {@code true} if {@link #getTimeUncertaintyNanos()} is available, {@code false} * otherwise. */ public boolean hasTimeUncertaintyNanos() { return isFlagSet(HAS_TIME_UNCERTAINTY); } /** * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds. * *
The uncertainty is represented as an absolute (single sided) value. * *
The value is only available if {@link #hasTimeUncertaintyNanos()} is {@code true}. * *
This value is often effectively zero (it is the reference clock by which all other times * and time uncertainties are measured), and thus this field may often be 0, or not provided. */ public double getTimeUncertaintyNanos() { return mTimeUncertaintyNanos; } /** * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds. * @hide */ @TestApi public void setTimeUncertaintyNanos(double timeUncertaintyNanos) { setFlag(HAS_TIME_UNCERTAINTY); mTimeUncertaintyNanos = timeUncertaintyNanos; } /** * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds. * @hide */ @TestApi public void resetTimeUncertaintyNanos() { resetFlag(HAS_TIME_UNCERTAINTY); mTimeUncertaintyNanos = Double.NaN; } /** * Returns {@code true} if {@link #getFullBiasNanos()} is available, {@code false} otherwise. */ public boolean hasFullBiasNanos() { return isFlagSet(HAS_FULL_BIAS); } /** * Gets the difference between hardware clock ({@link #getTimeNanos()}) inside GPS receiver and * the true GPS time since 0000Z, January 6, 1980, in nanoseconds. * *
This value is available if the receiver has estimated GPS time. If the computed time is * for a non-GPS constellation, the time offset of that constellation to GPS has to be applied * to fill this value. The value is only available if {@link #hasFullBiasNanos()} is * {@code true}. * *
The error estimate for the sum of this field and {@link #getBiasNanos} is * {@link #getBiasUncertaintyNanos()}. * *
The sign of the value is defined by the following equation: * *
* local estimate of GPS time = TimeNanos - (FullBiasNanos + BiasNanos)*/ public long getFullBiasNanos() { return mFullBiasNanos; } /** * Sets the full bias in nanoseconds. * @hide */ @TestApi public void setFullBiasNanos(long value) { setFlag(HAS_FULL_BIAS); mFullBiasNanos = value; } /** * Resets the full bias in nanoseconds. * @hide */ @TestApi public void resetFullBiasNanos() { resetFlag(HAS_FULL_BIAS); mFullBiasNanos = Long.MIN_VALUE; } /** * Returns {@code true} if {@link #getBiasNanos()} is available, {@code false} otherwise. */ public boolean hasBiasNanos() { return isFlagSet(HAS_BIAS); } /** * Gets the clock's sub-nanosecond bias. * *
See the description of how this field is part of converting from hardware clock time, to * GPS time, in {@link #getFullBiasNanos()}. * *
The error estimate for the sum of this field and {@link #getFullBiasNanos} is * {@link #getBiasUncertaintyNanos()}. * *
The value is only available if {@link #hasBiasNanos()} is {@code true}. */ public double getBiasNanos() { return mBiasNanos; } /** * Sets the sub-nanosecond bias. * @hide */ @TestApi public void setBiasNanos(double biasNanos) { setFlag(HAS_BIAS); mBiasNanos = biasNanos; } /** * Resets the clock's Bias in nanoseconds. * @hide */ @TestApi public void resetBiasNanos() { resetFlag(HAS_BIAS); mBiasNanos = Double.NaN; } /** * Returns {@code true} if {@link #getBiasUncertaintyNanos()} is available, {@code false} * otherwise. */ public boolean hasBiasUncertaintyNanos() { return isFlagSet(HAS_BIAS_UNCERTAINTY); } /** * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds. * *
See the description of how this field provides the error estimate in the conversion from * hardware clock time, to GPS time, in {@link #getFullBiasNanos()}. * *
The value is only available if {@link #hasBiasUncertaintyNanos()} is {@code true}. */ public double getBiasUncertaintyNanos() { return mBiasUncertaintyNanos; } /** * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds. * @hide */ @TestApi public void setBiasUncertaintyNanos(double biasUncertaintyNanos) { setFlag(HAS_BIAS_UNCERTAINTY); mBiasUncertaintyNanos = biasUncertaintyNanos; } /** * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds. * @hide */ @TestApi public void resetBiasUncertaintyNanos() { resetFlag(HAS_BIAS_UNCERTAINTY); mBiasUncertaintyNanos = Double.NaN; } /** * Returns {@code true} if {@link #getDriftNanosPerSecond()} is available, {@code false} * otherwise. */ public boolean hasDriftNanosPerSecond() { return isFlagSet(HAS_DRIFT); } /** * Gets the clock's Drift in nanoseconds per second. * *
A positive value indicates that the frequency is higher than the nominal (e.g. GPS master * clock) frequency. The error estimate for this reported drift is * {@link #getDriftUncertaintyNanosPerSecond()}. * *
The value is only available if {@link #hasDriftNanosPerSecond()} is {@code true}. */ public double getDriftNanosPerSecond() { return mDriftNanosPerSecond; } /** * Sets the clock's Drift in nanoseconds per second. * @hide */ @TestApi public void setDriftNanosPerSecond(double driftNanosPerSecond) { setFlag(HAS_DRIFT); mDriftNanosPerSecond = driftNanosPerSecond; } /** * Resets the clock's Drift in nanoseconds per second. * @hide */ @TestApi public void resetDriftNanosPerSecond() { resetFlag(HAS_DRIFT); mDriftNanosPerSecond = Double.NaN; } /** * Returns {@code true} if {@link #getDriftUncertaintyNanosPerSecond()} is available, * {@code false} otherwise. */ public boolean hasDriftUncertaintyNanosPerSecond() { return isFlagSet(HAS_DRIFT_UNCERTAINTY); } /** * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second. * *
The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is * {@code true}. */ public double getDriftUncertaintyNanosPerSecond() { return mDriftUncertaintyNanosPerSecond; } /** * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second. * @hide */ @TestApi public void setDriftUncertaintyNanosPerSecond(double driftUncertaintyNanosPerSecond) { setFlag(HAS_DRIFT_UNCERTAINTY); mDriftUncertaintyNanosPerSecond = driftUncertaintyNanosPerSecond; } /** * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second. * @hide */ @TestApi public void resetDriftUncertaintyNanosPerSecond() { resetFlag(HAS_DRIFT_UNCERTAINTY); mDriftUncertaintyNanosPerSecond = Double.NaN; } /** * Gets count of hardware clock discontinuities. * *
When this value stays the same, vs. a value in a previously reported {@link GnssClock}, it * can be safely assumed that the {@code TimeNanos} value has been derived from a clock that has * been running continuously - e.g. a single continuously powered crystal oscillator, and thus * the {@code (FullBiasNanos + BiasNanos)} offset can be modelled with traditional clock bias * & drift models. * *
Each time this value changes, vs. the value in a previously reported {@link GnssClock},
* that suggests the hardware clock may have experienced a discontinuity (e.g. a power cycle or
* other anomaly), so that any assumptions about modelling a smoothly changing
* {@code (FullBiasNanos + BiasNanos)} offset, and a smoothly growing {@code (TimeNanos)}
* between this and the previously reported {@code GnssClock}, should be reset.
*/
public int getHardwareClockDiscontinuityCount() {
return mHardwareClockDiscontinuityCount;
}
/**
* Sets count of last hardware clock discontinuity.
* @hide
*/
@TestApi
public void setHardwareClockDiscontinuityCount(int value) {
mHardwareClockDiscontinuityCount = value;
}
public static final Creator