/*
 * 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 GPS clock timestamp.
 *
 * <p>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);
    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
     * &amp; 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;
    }
}
