This is more correct. Android devices, even under ideal conditions, don't track UTC (which contains leap seconds and uses the SI definition of a second) but use a clock based on Unix epoch time (no leap seconds, but clocks may skip/stop or smear around leap seconds to ensure a fixed number of second increments per calendar day when leap seconds are applied to UTC). Bug: 218802673 Test: Compile only Change-Id: If87023af06ba9933f96029e52df9cb3841bca0cb
811 lines
27 KiB
Java
811 lines
27 KiB
Java
/*
|
|
* 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.FloatRange;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.TestApi;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
|
|
/**
|
|
* A class containing a GNSS clock timestamp.
|
|
*
|
|
* <p>It represents a measurement of the GNSS 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);
|
|
private static final int HAS_ELAPSED_REALTIME_NANOS = (1 << 7);
|
|
private static final int HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS = (1 << 8);
|
|
private static final int HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB = (1 << 9);
|
|
private static final int HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB = (1 << 10);
|
|
private static final int HAS_REFERENCE_CODE_TYPE_FOR_ISB = (1 << 11);
|
|
|
|
// 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;
|
|
private long mElapsedRealtimeNanos;
|
|
private double mElapsedRealtimeUncertaintyNanos;
|
|
private int mReferenceConstellationTypeForIsb;
|
|
private double mReferenceCarrierFrequencyHzForIsb;
|
|
private String mReferenceCodeTypeForIsb;
|
|
|
|
/**
|
|
* @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;
|
|
mElapsedRealtimeNanos = clock.mElapsedRealtimeNanos;
|
|
mElapsedRealtimeUncertaintyNanos = clock.mElapsedRealtimeUncertaintyNanos;
|
|
mReferenceConstellationTypeForIsb = clock.mReferenceConstellationTypeForIsb;
|
|
mReferenceCarrierFrequencyHzForIsb = clock.mReferenceCarrierFrequencyHzForIsb;
|
|
mReferenceCodeTypeForIsb = clock.mReferenceCodeTypeForIsb;
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* <p>The sign of the value is defined by the following equation:
|
|
* <pre>
|
|
* UtcTimeNanos = TimeNanos - (FullBiasNanos + BiasNanos) - LeapSecond * 1,000,000,000</pre>
|
|
*
|
|
* <p>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.
|
|
*
|
|
* <p>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()}.
|
|
*
|
|
* <p>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.
|
|
*
|
|
* <p>The uncertainty is represented as an absolute (single sided) value.
|
|
*
|
|
* <p>The value is only available if {@link #hasTimeUncertaintyNanos()} is {@code true}.
|
|
*
|
|
* <p>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.
|
|
*/
|
|
@FloatRange(from = 0.0f)
|
|
public double getTimeUncertaintyNanos() {
|
|
return mTimeUncertaintyNanos;
|
|
}
|
|
|
|
/**
|
|
* Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void setTimeUncertaintyNanos(@FloatRange(from = 0.0f) 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);
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* <p>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}.
|
|
*
|
|
* <p>The error estimate for the sum of this field and {@link #getBiasNanos} is
|
|
* {@link #getBiasUncertaintyNanos()}.
|
|
*
|
|
* <p>The sign of the value is defined by the following equation:
|
|
*
|
|
* <pre>
|
|
* local estimate of GPS time = TimeNanos - (FullBiasNanos + BiasNanos)</pre>
|
|
*/
|
|
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.
|
|
*
|
|
* <p>See the description of how this field is part of converting from hardware clock time, to
|
|
* GPS time, in {@link #getFullBiasNanos()}.
|
|
*
|
|
* <p>The error estimate for the sum of this field and {@link #getFullBiasNanos} is
|
|
* {@link #getBiasUncertaintyNanos()}.
|
|
*
|
|
* <p>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);
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* <p>See the description of how this field provides the error estimate in the conversion from
|
|
* hardware clock time, to GPS time, in {@link #getFullBiasNanos()}.
|
|
*
|
|
* <p>The value is only available if {@link #hasBiasUncertaintyNanos()} is {@code true}.
|
|
*/
|
|
@FloatRange(from = 0.0f)
|
|
public double getBiasUncertaintyNanos() {
|
|
return mBiasUncertaintyNanos;
|
|
}
|
|
|
|
/**
|
|
* Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void setBiasUncertaintyNanos(@FloatRange(from = 0.0f) 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);
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* <p>This value is the instantaneous time-derivative of the value provided by
|
|
* {@link #getBiasNanos()}.
|
|
*
|
|
* <p>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()}.
|
|
*
|
|
* <p>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);
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* <p>The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is
|
|
* {@code true}.
|
|
*/
|
|
@FloatRange(from = 0.0f)
|
|
public double getDriftUncertaintyNanosPerSecond() {
|
|
return mDriftUncertaintyNanosPerSecond;
|
|
}
|
|
|
|
/**
|
|
* Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void setDriftUncertaintyNanosPerSecond(
|
|
@FloatRange(from = 0.0f) 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);
|
|
}
|
|
|
|
/**
|
|
* Returns {@code true} if {@link #getElapsedRealtimeNanos()} is available, {@code false}
|
|
* otherwise.
|
|
*/
|
|
public boolean hasElapsedRealtimeNanos() {
|
|
return isFlagSet(HAS_ELAPSED_REALTIME_NANOS);
|
|
}
|
|
|
|
/**
|
|
* Returns the elapsed real-time of this clock since system boot, in nanoseconds.
|
|
*
|
|
* <p>The value is only available if {@link #hasElapsedRealtimeNanos()} is
|
|
* {@code true}.
|
|
*/
|
|
public long getElapsedRealtimeNanos() {
|
|
return mElapsedRealtimeNanos;
|
|
}
|
|
|
|
/**
|
|
* Sets the elapsed real-time of this clock since system boot, in nanoseconds.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void setElapsedRealtimeNanos(long elapsedRealtimeNanos) {
|
|
setFlag(HAS_ELAPSED_REALTIME_NANOS);
|
|
mElapsedRealtimeNanos = elapsedRealtimeNanos;
|
|
}
|
|
|
|
/**
|
|
* Resets the elapsed real-time of this clock since system boot, in nanoseconds.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void resetElapsedRealtimeNanos() {
|
|
resetFlag(HAS_ELAPSED_REALTIME_NANOS);
|
|
mElapsedRealtimeNanos = 0;
|
|
}
|
|
|
|
/**
|
|
* Returns {@code true} if {@link #getElapsedRealtimeUncertaintyNanos()} is available, {@code
|
|
* false} otherwise.
|
|
*/
|
|
public boolean hasElapsedRealtimeUncertaintyNanos() {
|
|
return isFlagSet(HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS);
|
|
}
|
|
|
|
/**
|
|
* Gets the estimate of the relative precision of the alignment of the
|
|
* {@link #getElapsedRealtimeNanos()} timestamp, with the reported measurements in
|
|
* nanoseconds (68% confidence).
|
|
*
|
|
* <p>The value is only available if {@link #hasElapsedRealtimeUncertaintyNanos()} is
|
|
* {@code true}.
|
|
*/
|
|
@FloatRange(from = 0.0f)
|
|
public double getElapsedRealtimeUncertaintyNanos() {
|
|
return mElapsedRealtimeUncertaintyNanos;
|
|
}
|
|
|
|
/**
|
|
* Sets the estimate of the relative precision of the alignment of the
|
|
* {@link #getElapsedRealtimeNanos()} timestamp, with the reported measurements in
|
|
* nanoseconds (68% confidence).
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void setElapsedRealtimeUncertaintyNanos(
|
|
@FloatRange(from = 0.0f) double elapsedRealtimeUncertaintyNanos) {
|
|
setFlag(HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS);
|
|
mElapsedRealtimeUncertaintyNanos = elapsedRealtimeUncertaintyNanos;
|
|
}
|
|
|
|
/**
|
|
* Resets the estimate of the relative precision of the alignment of the
|
|
* {@link #getElapsedRealtimeNanos()} timestamp, with the reported measurements in
|
|
* nanoseconds (68% confidence).
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void resetElapsedRealtimeUncertaintyNanos() {
|
|
resetFlag(HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS);
|
|
}
|
|
|
|
/**
|
|
* Returns {@code true} if {@link #getReferenceConstellationTypeForIsb()} is available,
|
|
* {@code false} otherwise.
|
|
*/
|
|
public boolean hasReferenceConstellationTypeForIsb() {
|
|
return isFlagSet(HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB);
|
|
}
|
|
|
|
/**
|
|
* Returns the reference constellation type for inter-signal bias.
|
|
*
|
|
* <p>The value is only available if {@link #hasReferenceConstellationTypeForIsb()} is
|
|
* {@code true}.
|
|
*
|
|
* <p>The return value is one of those constants with {@code CONSTELLATION_} prefix in
|
|
* {@link GnssStatus}.
|
|
*/
|
|
@GnssStatus.ConstellationType
|
|
public int getReferenceConstellationTypeForIsb() {
|
|
return mReferenceConstellationTypeForIsb;
|
|
}
|
|
|
|
/**
|
|
* Sets the reference constellation type for inter-signal bias.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void setReferenceConstellationTypeForIsb(@GnssStatus.ConstellationType int value) {
|
|
setFlag(HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB);
|
|
mReferenceConstellationTypeForIsb = value;
|
|
}
|
|
|
|
/**
|
|
* Resets the reference constellation type for inter-signal bias.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void resetReferenceConstellationTypeForIsb() {
|
|
resetFlag(HAS_REFERENCE_CONSTELLATION_TYPE_FOR_ISB);
|
|
mReferenceConstellationTypeForIsb = GnssStatus.CONSTELLATION_UNKNOWN;
|
|
}
|
|
|
|
/**
|
|
* Returns {@code true} if {@link #getReferenceCarrierFrequencyHzForIsb()} is available, {@code
|
|
* false} otherwise.
|
|
*/
|
|
public boolean hasReferenceCarrierFrequencyHzForIsb() {
|
|
return isFlagSet(HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB);
|
|
}
|
|
|
|
/**
|
|
* Returns the reference carrier frequency in Hz for inter-signal bias.
|
|
*
|
|
* <p>The value is only available if {@link #hasReferenceCarrierFrequencyHzForIsb()} is
|
|
* {@code true}.
|
|
*/
|
|
@FloatRange(from = 0.0)
|
|
public double getReferenceCarrierFrequencyHzForIsb() {
|
|
return mReferenceCarrierFrequencyHzForIsb;
|
|
}
|
|
|
|
/**
|
|
* Sets the reference carrier frequency in Hz for inter-signal bias.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void setReferenceCarrierFrequencyHzForIsb(@FloatRange(from = 0.0) double value) {
|
|
setFlag(HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB);
|
|
mReferenceCarrierFrequencyHzForIsb = value;
|
|
}
|
|
|
|
/**
|
|
* Resets the reference carrier frequency in Hz for inter-signal bias.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void resetReferenceCarrierFrequencyHzForIsb() {
|
|
resetFlag(HAS_REFERENCE_CARRIER_FREQUENCY_FOR_ISB);
|
|
}
|
|
|
|
/**
|
|
* Returns {@code true} if {@link #getReferenceCodeTypeForIsb()} is available, {@code
|
|
* false} otherwise.
|
|
*/
|
|
public boolean hasReferenceCodeTypeForIsb() {
|
|
return isFlagSet(HAS_REFERENCE_CODE_TYPE_FOR_ISB);
|
|
}
|
|
|
|
/**
|
|
* Returns the reference code type for inter-signal bias.
|
|
*
|
|
* <p>The value is only available if {@link #hasReferenceCodeTypeForIsb()} is
|
|
* {@code true}.
|
|
*
|
|
* <p>The return value is one of those constants defined in
|
|
* {@link GnssMeasurement#getCodeType()}.
|
|
*/
|
|
@NonNull
|
|
public String getReferenceCodeTypeForIsb() {
|
|
return mReferenceCodeTypeForIsb;
|
|
}
|
|
|
|
/**
|
|
* Sets the reference code type for inter-signal bias.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void setReferenceCodeTypeForIsb(@NonNull String codeType) {
|
|
setFlag(HAS_REFERENCE_CODE_TYPE_FOR_ISB);
|
|
mReferenceCodeTypeForIsb = codeType;
|
|
}
|
|
|
|
/**
|
|
* Resets the reference code type for inter-signal bias.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public void resetReferenceCodeTypeForIsb() {
|
|
resetFlag(HAS_REFERENCE_CODE_TYPE_FOR_ISB);
|
|
mReferenceCodeTypeForIsb = "UNKNOWN";
|
|
}
|
|
|
|
/**
|
|
* Gets count of hardware clock discontinuities.
|
|
*
|
|
* <p>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.
|
|
*
|
|
* <p>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 @android.annotation.NonNull Creator<GnssClock> CREATOR = new Creator<GnssClock>() {
|
|
@Override
|
|
public GnssClock createFromParcel(Parcel parcel) {
|
|
GnssClock gpsClock = new GnssClock();
|
|
|
|
gpsClock.mFlags = parcel.readInt();
|
|
gpsClock.mLeapSecond = parcel.readInt();
|
|
gpsClock.mTimeNanos = parcel.readLong();
|
|
gpsClock.mTimeUncertaintyNanos = parcel.readDouble();
|
|
gpsClock.mFullBiasNanos = parcel.readLong();
|
|
gpsClock.mBiasNanos = parcel.readDouble();
|
|
gpsClock.mBiasUncertaintyNanos = parcel.readDouble();
|
|
gpsClock.mDriftNanosPerSecond = parcel.readDouble();
|
|
gpsClock.mDriftUncertaintyNanosPerSecond = parcel.readDouble();
|
|
gpsClock.mHardwareClockDiscontinuityCount = parcel.readInt();
|
|
gpsClock.mElapsedRealtimeNanos = parcel.readLong();
|
|
gpsClock.mElapsedRealtimeUncertaintyNanos = parcel.readDouble();
|
|
gpsClock.mReferenceConstellationTypeForIsb = parcel.readInt();
|
|
gpsClock.mReferenceCarrierFrequencyHzForIsb = parcel.readDouble();
|
|
gpsClock.mReferenceCodeTypeForIsb = parcel.readString();
|
|
|
|
return gpsClock;
|
|
}
|
|
|
|
@Override
|
|
public GnssClock[] newArray(int size) {
|
|
return new GnssClock[size];
|
|
}
|
|
};
|
|
|
|
@Override
|
|
public void writeToParcel(Parcel parcel, int flags) {
|
|
parcel.writeInt(mFlags);
|
|
parcel.writeInt(mLeapSecond);
|
|
parcel.writeLong(mTimeNanos);
|
|
parcel.writeDouble(mTimeUncertaintyNanos);
|
|
parcel.writeLong(mFullBiasNanos);
|
|
parcel.writeDouble(mBiasNanos);
|
|
parcel.writeDouble(mBiasUncertaintyNanos);
|
|
parcel.writeDouble(mDriftNanosPerSecond);
|
|
parcel.writeDouble(mDriftUncertaintyNanosPerSecond);
|
|
parcel.writeInt(mHardwareClockDiscontinuityCount);
|
|
parcel.writeLong(mElapsedRealtimeNanos);
|
|
parcel.writeDouble(mElapsedRealtimeUncertaintyNanos);
|
|
parcel.writeInt(mReferenceConstellationTypeForIsb);
|
|
parcel.writeDouble(mReferenceCarrierFrequencyHzForIsb);
|
|
parcel.writeString(mReferenceCodeTypeForIsb);
|
|
}
|
|
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
final String format = " %-15s = %s\n";
|
|
final String formatWithUncertainty = " %-15s = %-25s %-26s = %s\n";
|
|
StringBuilder builder = new StringBuilder("GnssClock:\n");
|
|
|
|
if (hasLeapSecond()) {
|
|
builder.append(String.format(format, "LeapSecond", mLeapSecond));
|
|
}
|
|
|
|
builder.append(String.format(
|
|
formatWithUncertainty,
|
|
"TimeNanos",
|
|
mTimeNanos,
|
|
"TimeUncertaintyNanos",
|
|
hasTimeUncertaintyNanos() ? mTimeUncertaintyNanos : null));
|
|
|
|
if (hasFullBiasNanos()) {
|
|
builder.append(String.format(format, "FullBiasNanos", mFullBiasNanos));
|
|
}
|
|
|
|
if (hasBiasNanos() || hasBiasUncertaintyNanos()) {
|
|
builder.append(String.format(
|
|
formatWithUncertainty,
|
|
"BiasNanos",
|
|
hasBiasNanos() ? mBiasNanos : null,
|
|
"BiasUncertaintyNanos",
|
|
hasBiasUncertaintyNanos() ? mBiasUncertaintyNanos : null));
|
|
}
|
|
|
|
if (hasDriftNanosPerSecond() || hasDriftUncertaintyNanosPerSecond()) {
|
|
builder.append(String.format(
|
|
formatWithUncertainty,
|
|
"DriftNanosPerSecond",
|
|
hasDriftNanosPerSecond() ? mDriftNanosPerSecond : null,
|
|
"DriftUncertaintyNanosPerSecond",
|
|
hasDriftUncertaintyNanosPerSecond() ? mDriftUncertaintyNanosPerSecond : null));
|
|
}
|
|
|
|
builder.append(String.format(
|
|
format,
|
|
"HardwareClockDiscontinuityCount",
|
|
mHardwareClockDiscontinuityCount));
|
|
|
|
if (hasElapsedRealtimeNanos() || hasElapsedRealtimeUncertaintyNanos()) {
|
|
builder.append(String.format(
|
|
formatWithUncertainty,
|
|
"ElapsedRealtimeNanos",
|
|
hasElapsedRealtimeNanos() ? mElapsedRealtimeNanos : null,
|
|
"ElapsedRealtimeUncertaintyNanos",
|
|
hasElapsedRealtimeUncertaintyNanos() ? mElapsedRealtimeUncertaintyNanos
|
|
: null));
|
|
}
|
|
|
|
if (hasReferenceConstellationTypeForIsb()) {
|
|
builder.append(String.format(format, "ReferenceConstellationTypeForIsb",
|
|
mReferenceConstellationTypeForIsb));
|
|
}
|
|
|
|
if (hasReferenceCarrierFrequencyHzForIsb()) {
|
|
builder.append(String.format(format, "ReferenceCarrierFrequencyHzForIsb",
|
|
mReferenceCarrierFrequencyHzForIsb));
|
|
}
|
|
|
|
if (hasReferenceCodeTypeForIsb()) {
|
|
builder.append(
|
|
String.format(format, "ReferenceCodeTypeForIsb", mReferenceCodeTypeForIsb));
|
|
}
|
|
|
|
return builder.toString();
|
|
}
|
|
|
|
private void initialize() {
|
|
mFlags = HAS_NO_FLAGS;
|
|
resetLeapSecond();
|
|
setTimeNanos(Long.MIN_VALUE);
|
|
resetTimeUncertaintyNanos();
|
|
resetFullBiasNanos();
|
|
resetBiasNanos();
|
|
resetBiasUncertaintyNanos();
|
|
resetDriftNanosPerSecond();
|
|
resetDriftUncertaintyNanosPerSecond();
|
|
setHardwareClockDiscontinuityCount(Integer.MIN_VALUE);
|
|
resetElapsedRealtimeNanos();
|
|
resetElapsedRealtimeUncertaintyNanos();
|
|
resetReferenceConstellationTypeForIsb();
|
|
resetReferenceCarrierFrequencyHzForIsb();
|
|
resetReferenceCodeTypeForIsb();
|
|
}
|
|
|
|
private void setFlag(int flag) {
|
|
mFlags |= flag;
|
|
}
|
|
|
|
private void resetFlag(int flag) {
|
|
mFlags &= ~flag;
|
|
}
|
|
|
|
private boolean isFlagSet(int flag) {
|
|
return (mFlags & flag) == flag;
|
|
}
|
|
}
|