diff options
Diffstat (limited to 'location/java/android/location/GpsMeasurement.java')
-rw-r--r-- | location/java/android/location/GpsMeasurement.java | 1387 |
1 files changed, 1387 insertions, 0 deletions
diff --git a/location/java/android/location/GpsMeasurement.java b/location/java/android/location/GpsMeasurement.java new file mode 100644 index 0000000..1550dc2 --- /dev/null +++ b/location/java/android/location/GpsMeasurement.java @@ -0,0 +1,1387 @@ +/* + * 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.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +/** + * A class representing a GPS satellite measurement, containing raw and computed information. + * + * @hide + */ +public class GpsMeasurement implements Parcelable { + private static final String TAG = "GpsMeasurement"; + + private int mFlags; + private byte mPrn; + private double mTimeOffsetInNs; + private short mState; + private long mReceivedGpsTowInNs; + private long mReceivedGpsTowUncertaintyInNs; + private double mCn0InDbHz; + private double mPseudorangeRateInMetersPerSec; + private double mPseudorangeRateUncertaintyInMetersPerSec; + private short mAccumulatedDeltaRangeState; + private double mAccumulatedDeltaRangeInMeters; + private double mAccumulatedDeltaRangeUncertaintyInMeters; + private double mPseudorangeInMeters; + private double mPseudorangeUncertaintyInMeters; + private double mCodePhaseInChips; + private double mCodePhaseUncertaintyInChips; + private float mCarrierFrequencyInHz; + private long mCarrierCycles; + private double mCarrierPhase; + private double mCarrierPhaseUncertainty; + private byte mLossOfLock; + private int mBitNumber; + private short mTimeFromLastBitInMs; + private double mDopplerShiftInHz; + private double mDopplerShiftUncertaintyInHz; + private byte mMultipathIndicator; + private double mSnrInDb; + private double mElevationInDeg; + private double mElevationUncertaintyInDeg; + private double mAzimuthInDeg; + private double mAzimuthUncertaintyInDeg; + private boolean mUsedInFix; + + // 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_SNR = (1<<0); + private static final int HAS_ELEVATION = (1<<1); + private static final int HAS_ELEVATION_UNCERTAINTY = (1<<2); + private static final int HAS_AZIMUTH = (1<<3); + private static final int HAS_AZIMUTH_UNCERTAINTY = (1<<4); + private static final int HAS_PSEUDORANGE = (1<<5); + private static final int HAS_PSEUDORANGE_UNCERTAINTY = (1<<6); + private static final int HAS_CODE_PHASE = (1<<7); + private static final int HAS_CODE_PHASE_UNCERTAINTY = (1<<8); + private static final int HAS_CARRIER_FREQUENCY = (1<<9); + private static final int HAS_CARRIER_CYCLES = (1<<10); + private static final int HAS_CARRIER_PHASE = (1<<11); + private static final int HAS_CARRIER_PHASE_UNCERTAINTY = (1<<12); + private static final int HAS_BIT_NUMBER = (1<<13); + private static final int HAS_TIME_FROM_LAST_BIT = (1<<14); + private static final int HAS_DOPPLER_SHIFT = (1<<15); + private static final int HAS_DOPPLER_SHIFT_UNCERTAINTY = (1<<16); + + /** + * The indicator is not available or it is unknown. + */ + public static final byte LOSS_OF_LOCK_UNKNOWN = 0; + + /** + * The measurement does not present any indication of 'loss of lock'. + */ + public static final byte LOSS_OF_LOCK_OK = 1; + + /** + * 'Loss of lock' detected between the previous and current observation: cycle slip possible. + */ + public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; + + /** + * The indicator is not available or it is unknown. + */ + public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; + + /** + * The measurement has been indicated to use multi-path. + */ + public static final byte MULTIPATH_INDICATOR_DETECTED = 1; + + /** + * The measurement has been indicated not tu use multi-path. + */ + public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; + + /** + * The state of GPS receiver the measurement is invalid or unknown. + */ + public static final short STATE_UNKNOWN = 0; + + /** + * The state of the GPS receiver is ranging code lock. + */ + public static final short STATE_CODE_LOCK = (1<<0); + + /** + * The state of the GPS receiver is in bit sync. + */ + public static final short STATE_BIT_SYNC = (1<<1); + + /** + *The state of the GPS receiver is in sub-frame sync. + */ + public static final short STATE_SUBFRAME_SYNC = (1<<2); + + /** + * The state of the GPS receiver has TOW decoded. + */ + public static final short STATE_TOW_DECODED = (1<<3); + + /** + * The state of the 'Accumulated Delta Range' is invalid or unknown. + */ + public static final short ADR_STATE_UNKNOWN = 0; + + /** + * The state of the 'Accumulated Delta Range' is valid. + */ + public static final short ADR_STATE_VALID = (1<<0); + + /** + * The state of the 'Accumulated Delta Range' has detected a reset. + */ + public static final short ADR_STATE_RESET = (1<<1); + + /** + * The state of the 'Accumulated Delta Range' has a cycle slip detected. + */ + public static final short ADR_STATE_CYCLE_SLIP = (1<<2); + + // End enumerations in sync with gps.h + + GpsMeasurement() { + initialize(); + } + + /** + * Sets all contents to the values stored in the provided object. + */ + public void set(GpsMeasurement measurement) { + mFlags = measurement.mFlags; + mPrn = measurement.mPrn; + mTimeOffsetInNs = measurement.mTimeOffsetInNs; + mState = measurement.mState; + mReceivedGpsTowInNs = measurement.mReceivedGpsTowInNs; + mReceivedGpsTowUncertaintyInNs = measurement.mReceivedGpsTowUncertaintyInNs; + mCn0InDbHz = measurement.mCn0InDbHz; + mPseudorangeRateInMetersPerSec = measurement.mPseudorangeRateInMetersPerSec; + mPseudorangeRateUncertaintyInMetersPerSec = + measurement.mPseudorangeRateUncertaintyInMetersPerSec; + mAccumulatedDeltaRangeState = measurement.mAccumulatedDeltaRangeState; + mAccumulatedDeltaRangeInMeters = measurement.mAccumulatedDeltaRangeInMeters; + mAccumulatedDeltaRangeUncertaintyInMeters = + measurement.mAccumulatedDeltaRangeUncertaintyInMeters; + mPseudorangeInMeters = measurement.mPseudorangeInMeters; + mPseudorangeUncertaintyInMeters = measurement.mPseudorangeUncertaintyInMeters; + mCodePhaseInChips = measurement.mCodePhaseInChips; + mCodePhaseUncertaintyInChips = measurement.mCodePhaseUncertaintyInChips; + mCarrierFrequencyInHz = measurement.mCarrierFrequencyInHz; + mCarrierCycles = measurement.mCarrierCycles; + mCarrierPhase = measurement.mCarrierPhase; + mCarrierPhaseUncertainty = measurement.mCarrierPhaseUncertainty; + mLossOfLock = measurement.mLossOfLock; + mBitNumber = measurement.mBitNumber; + mTimeFromLastBitInMs = measurement.mTimeFromLastBitInMs; + mDopplerShiftInHz = measurement.mDopplerShiftInHz; + mDopplerShiftUncertaintyInHz = measurement.mDopplerShiftUncertaintyInHz; + mMultipathIndicator = measurement.mMultipathIndicator; + mSnrInDb = measurement.mSnrInDb; + mElevationInDeg = measurement.mElevationInDeg; + mElevationUncertaintyInDeg = measurement.mElevationUncertaintyInDeg; + mAzimuthInDeg = measurement.mAzimuthInDeg; + mAzimuthUncertaintyInDeg = measurement.mAzimuthUncertaintyInDeg; + mUsedInFix = measurement.mUsedInFix; + } + + /** + * Resets all the contents to its original state. + */ + public void reset() { + initialize(); + } + + /** + * Gets the Pseudo-random number (PRN). + * Range: [1, 32] + */ + public byte getPrn() { + return mPrn; + } + + /** + * Sets the Pseud-random number (PRN). + */ + public void setPrn(byte value) { + mPrn = value; + } + + /** + * Gets the time offset at which the measurement was taken in nanoseconds. + * The reference receiver's time is specified by {@link GpsClock#getTimeInNs()} and should be + * interpreted in the same way as indicated by {@link GpsClock#getType()}. + * + * The sign of this value is given by the following equation: + * measurement time = time_ns + time_offset_ns + * + * The value provides an individual time-stamp for the measurement, and allows sub-nanosecond + * accuracy. + */ + public double getTimeOffsetInNs() { + return mTimeOffsetInNs; + } + + /** + * Sets the time offset at which the measurement was taken in nanoseconds. + */ + public void setTimeOffsetInNs(double value) { + mTimeOffsetInNs = value; + } + + /** + * Gets per-satellite sync state. + * It represents the current sync state for the associated satellite. + * + * This value helps interpret {@link #getReceivedGpsTowInNs()}. + */ + public short getState() { + return mState; + } + + /** + * Sets the sync state. + */ + public void setState(short value) { + switch (value) { + case STATE_UNKNOWN: + case STATE_BIT_SYNC: + case STATE_CODE_LOCK: + case STATE_SUBFRAME_SYNC: + case STATE_TOW_DECODED: + mState = value; + break; + default: + Log.d(TAG, "Sanitizing invalid 'sync state': " + value); + mState = STATE_UNKNOWN; + break; + } + } + + /** + * Gets a string representation of the 'sync state'. + * For internal and logging use only. + */ + private String getStateString() { + switch (mState) { + case STATE_UNKNOWN: + return "Unknown"; + case STATE_BIT_SYNC: + return "BitSync"; + case STATE_CODE_LOCK: + return "CodeLock"; + case STATE_SUBFRAME_SYNC: + return "SubframeSync"; + case STATE_TOW_DECODED: + return "TowDecoded"; + default: + return "<Invalid>"; + } + } + + /** + * Gets the received GPS Time-of-Week at the measurement time, in nanoseconds. + * The value is relative to the beginning of the current GPS week. + * + * Given {@link #getState()} of the GPS receiver, the range of this field can be: + * Searching : [ 0 ] : {@link #STATE_UNKNOWN} is set + * Ranging code lock : [ 0 1 ms ] : {@link #STATE_CODE_LOCK} is set + * Bit sync : [ 0 20 ms ] : {@link #STATE_BIT_SYNC} is set + * Subframe sync : [ 0 6 ms ] : {@link #STATE_SUBFRAME_SYNC} is set + * TOW decoded : [ 0 1 week ] : {@link #STATE_TOW_DECODED} is set + */ + public long getReceivedGpsTowInNs() { + return mReceivedGpsTowInNs; + } + + /** + * Sets the received GPS time-of-week in nanoseconds. + */ + public void setReceivedGpsTowInNs(long value) { + mReceivedGpsTowInNs = value; + } + + /** + * Gets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds. + */ + public long getReceivedGpsTowUncertaintyInNs() { + return mReceivedGpsTowUncertaintyInNs; + } + + /** + * Sets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds. + */ + public void setReceivedGpsTowUncertaintyInNs(long value) { + mReceivedGpsTowUncertaintyInNs = value; + } + + /** + * Gets the Carrier-to-noise density in dB-Hz. + * Range: [0, 63]. + * + * The value contains the measured C/N0 for the signal at the antenna input. + */ + public double getCn0InDbHz() { + return mCn0InDbHz; + } + + /** + * Sets the carrier-to-noise density in dB-Hz. + */ + public void setCn0InDbHz(double value) { + mCn0InDbHz = value; + } + + /** + * Gets the Pseudorange rate at the timestamp in m/s. + * The reported value includes {@link #getPseudorangeRateUncertaintyInMetersPerSec()}. + */ + public double getPseudorangeRateInMetersPerSec() { + return mPseudorangeRateInMetersPerSec; + } + + /** + * Sets the pseudorange rate at the timestamp in m/s. + */ + public void setPseudorangeRateInMetersPerSec(double value) { + mPseudorangeRateInMetersPerSec = value; + } + + /** + * Gets the pseudorange's rate uncertainty (1-Sigma) in m/s. + * The uncertainty is represented as an absolute (single sided) value. + */ + public double getPseudorangeRateUncertaintyInMetersPerSec() { + return mPseudorangeRateUncertaintyInMetersPerSec; + } + + /** + * Sets the pseudorange's rate uncertainty (1-Sigma) in m/s. + */ + public void setPseudorangeRateUncertaintyInMetersPerSec(double value) { + mPseudorangeRateUncertaintyInMetersPerSec = value; + } + + /** + * Gets 'Accumulated Delta Range' state. + * It indicates whether {@link #getAccumulatedDeltaRangeInMeters()} is reset or there is a + * cycle slip (indicating 'loss of lock'). + */ + public short getAccumulatedDeltaRangeState() { + return mAccumulatedDeltaRangeState; + } + + /** + * Sets the 'Accumulated Delta Range' state. + */ + public void setAccumulatedDeltaRangeState(short value) { + switch (value) { + case ADR_STATE_UNKNOWN: + case ADR_STATE_VALID: + case ADR_STATE_RESET: + case ADR_STATE_CYCLE_SLIP: + mAccumulatedDeltaRangeState = value; + break; + default: + Log.d(TAG, "Sanitizing invalid 'Accumulated Delta Range state': " + value); + mAccumulatedDeltaRangeState = ADR_STATE_UNKNOWN; + break; + } + } + + /** + * Gets a string representation of the 'Accumulated Delta Range state'. + * For internal and logging use only. + */ + private String getAccumulatedDeltaRangeStateString() { + switch (mAccumulatedDeltaRangeState) { + case ADR_STATE_UNKNOWN: + return "Unknown"; + case ADR_STATE_VALID: + return "Valid"; + case ADR_STATE_RESET: + return "Reset"; + case ADR_STATE_CYCLE_SLIP: + return "CycleSlip"; + default: + return "<Invalid>"; + } + } + + /** + * Gets the accumulated delta range since the last channel reset, in meters. + * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyInMeters()}. + * + * The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}. + */ + public double getAccumulatedDeltaRangeInMeters() { + return mAccumulatedDeltaRangeInMeters; + } + + /** + * Sets the accumulated delta range in meters. + */ + public void setAccumulatedDeltaRangeInMeters(double value) { + mAccumulatedDeltaRangeInMeters = value; + } + + /** + * Gets the accumulated delta range's uncertainty (1-Sigma) in meters. + * The uncertainty is represented as an absolute (single sided) value. + */ + public double getAccumulatedDeltaRangeUncertaintyInMeters() { + return mAccumulatedDeltaRangeUncertaintyInMeters; + } + + /** + * Sets the accumulated delta range's uncertainty (1-sigma) in meters. + * + * The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}. + */ + public void setAccumulatedDeltaRangeUncertaintyInMeters(double value) { + mAccumulatedDeltaRangeUncertaintyInMeters = value; + } + + /** + * Returns true if {@link #getPseudorangeInMeters()} is available, false otherwise. + */ + public boolean hasPseudorangeInMeters() { + return isFlagSet(HAS_PSEUDORANGE); + } + + /** + * Gets the best derived pseudorange by the chipset, in meters. + * The reported pseudorange includes {@link #getPseudorangeUncertaintyInMeters()}. + * + * The value is only available if {@link #hasPseudorangeInMeters()} is true. + */ + public double getPseudorangeInMeters() { + return mPseudorangeInMeters; + } + + /** + * Sets the Pseudo-range in meters. + */ + public void setPseudorangeInMeters(double value) { + setFlag(HAS_PSEUDORANGE); + mPseudorangeInMeters = value; + } + + /** + * Resets the Pseudo-range in meters. + */ + public void resetPseudorangeInMeters() { + resetFlag(HAS_PSEUDORANGE); + mPseudorangeInMeters = Double.NaN; + } + + /** + * Returns true if {@link #getPseudorangeUncertaintyInMeters()} is available, false otherwise. + */ + public boolean hasPseudorangeUncertaintyInMeters() { + return isFlagSet(HAS_PSEUDORANGE_UNCERTAINTY); + } + + /** + * Gets the pseudorange's uncertainty (1-Sigma) in meters. + * The value contains the 'pseudorange' and 'clock' uncertainty in it. + * The uncertainty is represented as an absolute (single sided) value. + * + * The value is only available if {@link #hasPseudorangeUncertaintyInMeters()} is true. + */ + public double getPseudorangeUncertaintyInMeters() { + return mPseudorangeUncertaintyInMeters; + } + + /** + * Sets the pseudo-range's uncertainty (1-Sigma) in meters. + */ + public void setPseudorangeUncertaintyInMeters(double value) { + setFlag(HAS_PSEUDORANGE_UNCERTAINTY); + mPseudorangeUncertaintyInMeters = value; + } + + /** + * Resets the pseudo-range's uncertainty (1-Sigma) in meters. + */ + public void resetPseudorangeUncertaintyInMeters() { + resetFlag(HAS_PSEUDORANGE_UNCERTAINTY); + mPseudorangeUncertaintyInMeters = Double.NaN; + } + + /** + * Returns true if {@link #getCodePhaseInChips()} is available, false otherwise. + */ + public boolean hasCodePhaseInChips() { + return isFlagSet(HAS_CODE_PHASE); + } + + /** + * Gets the fraction of the current C/A code cycle. + * Range: [0, 1023] + * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}. + * The reported code-phase includes {@link #getCodePhaseUncertaintyInChips()}. + * + * The value is only available if {@link #hasCodePhaseInChips()} is true. + */ + public double getCodePhaseInChips() { + return mCodePhaseInChips; + } + + /** + * Sets the Code-phase in chips. + */ + public void setCodePhaseInChips(double value) { + setFlag(HAS_CODE_PHASE); + mCodePhaseInChips = value; + } + + /** + * Resets the Code-phase in chips. + */ + public void resetCodePhaseInChips() { + resetFlag(HAS_CODE_PHASE); + mCodePhaseInChips = Double.NaN; + } + + /** + * Returns true if {@link #getCodePhaseUncertaintyInChips()} is available, false otherwise. + */ + public boolean hasCodePhaseUncertaintyInChips() { + return isFlagSet(HAS_CODE_PHASE_UNCERTAINTY); + } + + /** + * Gets the code-phase's uncertainty (1-Sigma) as a fraction of chips. + * The uncertainty is represented as an absolute (single sided) value. + * + * The value is only available if {@link #hasCodePhaseUncertaintyInChips()} is true. + */ + public double getCodePhaseUncertaintyInChips() { + return mCodePhaseUncertaintyInChips; + } + + /** + * Sets the Code-phase's uncertainty (1-Sigma) in fractions of chips. + */ + public void setCodePhaseUncertaintyInChips(double value) { + setFlag(HAS_CODE_PHASE_UNCERTAINTY); + mCodePhaseUncertaintyInChips = value; + } + + /** + * Resets the Code-phase's uncertainty (1-Sigma) in fractions of chips. + */ + public void resetCodePhaseUncertaintyInChips() { + resetFlag(HAS_CODE_PHASE_UNCERTAINTY); + mCodePhaseUncertaintyInChips = Double.NaN; + } + + /** + * Returns true if {@link #getCarrierFrequencyInHz()} is available, false otherwise. + */ + public boolean hasCarrierFrequencyInHz() { + return isFlagSet(HAS_CARRIER_FREQUENCY); + } + + /** + * Gets the carrier frequency at which codes and messages are modulated, it can be L1 or L2. + * If the field is not set, the carrier frequency corresponds to L1. + * + * The value is only available if {@link #hasCarrierFrequencyInHz()} is true. + */ + public float getCarrierFrequencyInHz() { + return mCarrierFrequencyInHz; + } + + /** + * Sets the Carrier frequency (L1 or L2) in Hz. + */ + public void setCarrierFrequencyInHz(float carrierFrequencyInHz) { + setFlag(HAS_CARRIER_FREQUENCY); + mCarrierFrequencyInHz = carrierFrequencyInHz; + } + + /** + * Resets the Carrier frequency (L1 or L2) in Hz. + */ + public void resetCarrierFrequencyInHz() { + resetFlag(HAS_CARRIER_FREQUENCY); + mCarrierFrequencyInHz = Float.NaN; + } + + /** + * Returns true if {@link #getCarrierCycles()} is available, false otherwise. + */ + public boolean hasCarrierCycles() { + return isFlagSet(HAS_CARRIER_CYCLES); + } + + /** + * The number of full carrier cycles between the satellite and the receiver. + * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}. + * + * The value is only available if {@link #hasCarrierCycles()} is true. + */ + public long getCarrierCycles() { + return mCarrierCycles; + } + + /** + * Sets the number of full carrier cycles between the satellite and the receiver. + */ + public void setCarrierCycles(long value) { + setFlag(HAS_CARRIER_CYCLES); + mCarrierCycles = value; + } + + /** + * Resets the number of full carrier cycles between the satellite and the receiver. + */ + public void resetCarrierCycles() { + resetFlag(HAS_CARRIER_CYCLES); + mCarrierCycles = Long.MIN_VALUE; + } + + /** + * Returns true if {@link #getCarrierPhase()} is available, false otherwise. + */ + public boolean hasCarrierPhase() { + return isFlagSet(HAS_CARRIER_PHASE); + } + + /** + * Gets the RF phase detected by the receiver. + * Range: [0.0, 1.0]. + * This is usually the fractional part of the complete carrier phase measurement. + * + * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}. + * The reported carrier-phase includes {@link #getCarrierPhaseUncertainty()}. + * + * The value is only available if {@link #hasCarrierPhase()} is true. + */ + public double getCarrierPhase() { + return mCarrierPhase; + } + + /** + * Sets the RF phase detected by the receiver. + */ + public void setCarrierPhase(double value) { + setFlag(HAS_CARRIER_PHASE); + mCarrierPhase = value; + } + + /** + * Resets the RF phase detected by the receiver. + */ + public void resetCarrierPhase() { + resetFlag(HAS_CARRIER_PHASE); + mCarrierPhase = Double.NaN; + } + + /** + * Returns true if {@link #getCarrierPhaseUncertainty()} is available, false otherwise. + */ + public boolean hasCarrierPhaseUncertainty() { + return isFlagSet(HAS_CARRIER_PHASE_UNCERTAINTY); + } + + /** + * Gets the carrier-phase's uncertainty (1-Sigma). + * The uncertainty is represented as an absolute (single sided) value. + * + * The value is only available if {@link #hasCarrierPhaseUncertainty()} is true. + */ + public double getCarrierPhaseUncertainty() { + return mCarrierPhaseUncertainty; + } + + /** + * Sets the Carrier-phase's uncertainty (1-Sigma) in cycles. + */ + public void setCarrierPhaseUncertainty(double value) { + setFlag(HAS_CARRIER_PHASE_UNCERTAINTY); + mCarrierPhaseUncertainty = value; + } + + /** + * Resets the Carrier-phase's uncertainty (1-Sigma) in cycles. + */ + public void resetCarrierPhaseUncertainty() { + resetFlag(HAS_CARRIER_PHASE_UNCERTAINTY); + mCarrierPhaseUncertainty = Double.NaN; + } + + /** + * Gets a value indicating the 'loss of lock' state of the event. + */ + public byte getLossOfLock() { + return mLossOfLock; + } + + /** + * Sets the 'loss of lock' status. + */ + public void setLossOfLock(byte value) { + switch (value) { + case LOSS_OF_LOCK_UNKNOWN: + case LOSS_OF_LOCK_OK: + case LOSS_OF_LOCK_CYCLE_SLIP: + mLossOfLock = value; + break; + default: + Log.d(TAG, "Sanitizing invalid 'loss of lock': " + value); + mLossOfLock = LOSS_OF_LOCK_UNKNOWN; + break; + } + } + + /** + * Gets a string representation of the 'loss of lock'. + * For internal and logging use only. + */ + private String getLossOfLockString() { + switch (mLossOfLock) { + case LOSS_OF_LOCK_UNKNOWN: + return "Unknown"; + case LOSS_OF_LOCK_OK: + return "Ok"; + case LOSS_OF_LOCK_CYCLE_SLIP: + return "CycleSlip"; + default: + return "<Invalid>"; + } + } + + /** + * Returns true if {@link #getBitNumber()} is available, false otherwise. + */ + public boolean hasBitNumber() { + return isFlagSet(HAS_BIT_NUMBER); + } + + /** + * Gets the number of GPS bits transmitted since Sat-Sun midnight (GPS week). + * + * The value is only available if {@link #hasBitNumber()} is true. + */ + public int getBitNumber() { + return mBitNumber; + } + + /** + * Sets the bit number within the broadcast frame. + */ + public void setBitNumber(int bitNumber) { + setFlag(HAS_BIT_NUMBER); + mBitNumber = bitNumber; + } + + /** + * Resets the bit number within the broadcast frame. + */ + public void resetBitNumber() { + resetFlag(HAS_BIT_NUMBER); + mBitNumber = Integer.MIN_VALUE; + } + + /** + * Returns true if {@link #getTimeFromLastBitInMs()} is available, false otherwise. + */ + public boolean hasTimeFromLastBitInMs() { + return isFlagSet(HAS_TIME_FROM_LAST_BIT); + } + + /** + * Gets the elapsed time since the last received bit in milliseconds. + * Range: [0, 20]. + * + * The value is only available if {@link #hasTimeFromLastBitInMs()} is true. + */ + public short getTimeFromLastBitInMs() { + return mTimeFromLastBitInMs; + } + + /** + * Sets the elapsed time since the last received bit in milliseconds. + */ + public void setTimeFromLastBitInMs(short value) { + setFlag(HAS_TIME_FROM_LAST_BIT); + mTimeFromLastBitInMs = value; + } + + /** + * Resets the elapsed time since the last received bit in milliseconds. + */ + public void resetTimeFromLastBitInMs() { + resetFlag(HAS_TIME_FROM_LAST_BIT); + mTimeFromLastBitInMs = Short.MIN_VALUE; + } + + /** + * Returns true if {@link #getDopplerShiftInHz()} is available, false otherwise. + */ + public boolean hasDopplerShiftInHz() { + return isFlagSet(HAS_DOPPLER_SHIFT); + } + + /** + * Gets the Doppler Shift in Hz. + * A positive value indicates that the SV is moving toward the receiver. + * + * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}. + * The reported doppler shift includes {@link #getDopplerShiftUncertaintyInHz()}. + * + * The value is only available if {@link #hasDopplerShiftInHz()} is true. + */ + public double getDopplerShiftInHz() { + return mDopplerShiftInHz; + } + + /** + * Sets the Doppler shift in Hz. + */ + public void setDopplerShiftInHz(double value) { + setFlag(HAS_DOPPLER_SHIFT); + mDopplerShiftInHz = value; + } + + /** + * Resets the Doppler shift in Hz. + */ + public void resetDopplerShiftInHz() { + resetFlag(HAS_DOPPLER_SHIFT); + mDopplerShiftInHz = Double.NaN; + } + + /** + * Returns true if {@link #getDopplerShiftUncertaintyInHz()} is available, false otherwise. + */ + public boolean hasDopplerShiftUncertaintyInHz() { + return isFlagSet(HAS_DOPPLER_SHIFT_UNCERTAINTY); + } + + /** + * Gets the Doppler's Shift uncertainty (1-Sigma) in Hz. + * The uncertainty is represented as an absolute (single sided) value. + * + * The value is only available if {@link #hasDopplerShiftUncertaintyInHz()} is true. + */ + public double getDopplerShiftUncertaintyInHz() { + return mDopplerShiftUncertaintyInHz; + } + + /** + * Sets the Doppler's shift uncertainty (1-Sigma) in Hz. + */ + public void setDopplerShiftUncertaintyInHz(double value) { + setFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY); + mDopplerShiftUncertaintyInHz = value; + } + + /** + * Resets the Doppler's shift uncertainty (1-Sigma) in Hz. + */ + public void resetDopplerShiftUncertaintyInHz() { + resetFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY); + mDopplerShiftUncertaintyInHz = Double.NaN; + } + + /** + * Gets a value indicating the 'multipath' state of the event. + */ + public byte getMultipathIndicator() { + return mMultipathIndicator; + } + + /** + * Sets the 'multi-path' indicator. + */ + public void setMultipathIndicator(byte value) { + switch (value) { + case MULTIPATH_INDICATOR_UNKNOWN: + case MULTIPATH_INDICATOR_DETECTED: + case MULTIPATH_INDICATOR_NOT_USED: + mMultipathIndicator = value; + break; + default: + Log.d(TAG, "Sanitizing invalid 'muti-path indicator': " + value); + mMultipathIndicator = MULTIPATH_INDICATOR_UNKNOWN; + break; + } + } + + /** + * Gets a string representation of the 'multi-path indicator'. + * For internal and logging use only. + */ + private String getMultipathIndicatorString() { + switch(mMultipathIndicator) { + case MULTIPATH_INDICATOR_UNKNOWN: + return "Unknown"; + case MULTIPATH_INDICATOR_DETECTED: + return "Detected"; + case MULTIPATH_INDICATOR_NOT_USED: + return "NotUsed"; + default: + return "<Invalid>"; + } + } + + /** + * Returns true if {@link #getSnrInDb()} is available, false otherwise. + */ + public boolean hasSnrInDb() { + return isFlagSet(HAS_SNR); + } + + /** + * Gets the Signal-to-Noise ratio (SNR) in dB. + * + * The value is only available if {@link #hasSnrInDb()} is true. + */ + public double getSnrInDb() { + return mSnrInDb; + } + + /** + * Sets the Signal-to-noise ratio (SNR) in dB. + */ + public void setSnrInDb(double snrInDb) { + setFlag(HAS_SNR); + mSnrInDb = snrInDb; + } + + /** + * Resets the Signal-to-noise ratio (SNR) in dB. + */ + public void resetSnrInDb() { + resetFlag(HAS_SNR); + mSnrInDb = Double.NaN; + } + + /** + * Returns true if {@link #getElevationInDeg()} is available, false otherwise. + */ + public boolean hasElevationInDeg() { + return isFlagSet(HAS_ELEVATION); + } + + /** + * Gets the Elevation in degrees. + * Range: [-90, 90] + * The reported elevation includes {@link #getElevationUncertaintyInDeg()}. + * + * The value is only available if {@link #hasElevationInDeg()} is true. + */ + public double getElevationInDeg() { + return mElevationInDeg; + } + + /** + * Sets the Elevation in degrees. + */ + public void setElevationInDeg(double elevationInDeg) { + setFlag(HAS_ELEVATION); + mElevationInDeg = elevationInDeg; + } + + /** + * Resets the Elevation in degrees. + */ + public void resetElevationInDeg() { + resetFlag(HAS_ELEVATION); + mElevationInDeg = Double.NaN; + } + + /** + * Returns true if {@link #getElevationUncertaintyInDeg()} is available, false otherwise. + */ + public boolean hasElevationUncertaintyInDeg() { + return isFlagSet(HAS_ELEVATION_UNCERTAINTY); + } + + /** + * Gets the elevation's uncertainty (1-Sigma) in degrees. + * Range: [0, 90] + * + * The uncertainty is represented as an absolute (single sided) value. + * + * The value is only available if {@link #hasElevationUncertaintyInDeg()} is true. + */ + public double getElevationUncertaintyInDeg() { + return mElevationUncertaintyInDeg; + } + + /** + * Sets the elevation's uncertainty (1-Sigma) in degrees. + */ + public void setElevationUncertaintyInDeg(double value) { + setFlag(HAS_ELEVATION_UNCERTAINTY); + mElevationUncertaintyInDeg = value; + } + + /** + * Resets the elevation's uncertainty (1-Sigma) in degrees. + */ + public void resetElevationUncertaintyInDeg() { + resetFlag(HAS_ELEVATION_UNCERTAINTY); + mElevationUncertaintyInDeg = Double.NaN; + } + + /** + * Returns true if {@link #getAzimuthInDeg()} is available, false otherwise. + */ + public boolean hasAzimuthInDeg() { + return isFlagSet(HAS_AZIMUTH); + } + + /** + * Gets the azimuth in degrees. + * Range: [0, 360). + * + * The reported azimuth includes {@link #getAzimuthUncertaintyInDeg()}. + * + * The value is only available if {@link #hasAzimuthInDeg()} is true. + */ + public double getAzimuthInDeg() { + return mAzimuthInDeg; + } + + /** + * Sets the Azimuth in degrees. + */ + public void setAzimuthInDeg(double value) { + setFlag(HAS_AZIMUTH); + mAzimuthInDeg = value; + } + + /** + * Resets the Azimuth in degrees. + */ + public void resetAzimuthInDeg() { + resetFlag(HAS_AZIMUTH); + mAzimuthInDeg = Double.NaN; + } + + /** + * Returns true if {@link #getAzimuthUncertaintyInDeg()} is available, false otherwise. + */ + public boolean hasAzimuthUncertaintyInDeg() { + return isFlagSet(HAS_AZIMUTH_UNCERTAINTY); + } + + /** + * Gets the azimuth's uncertainty (1-Sigma) in degrees. + * Range: [0, 180]. + * + * The uncertainty is represented as an absolute (single sided) value. + * + * The value is only available if {@link #hasAzimuthUncertaintyInDeg()} is true. + */ + public double getAzimuthUncertaintyInDeg() { + return mAzimuthUncertaintyInDeg; + } + + /** + * Sets the Azimuth's uncertainty (1-Sigma) in degrees. + */ + public void setAzimuthUncertaintyInDeg(double value) { + setFlag(HAS_AZIMUTH_UNCERTAINTY); + mAzimuthUncertaintyInDeg = value; + } + + /** + * Resets the Azimuth's uncertainty (1-Sigma) in degrees. + */ + public void resetAzimuthUncertaintyInDeg() { + resetFlag(HAS_AZIMUTH_UNCERTAINTY); + mAzimuthUncertaintyInDeg = Double.NaN; + } + + /** + * Gets a flag indicating whether the GPS represented by the measurement was used for computing + * the most recent fix. + * + * @return A non-null value if the data is available, null otherwise. + */ + public boolean isUsedInFix() { + return mUsedInFix; + } + + /** + * Sets the Used-in-Fix flag. + */ + public void setUsedInFix(boolean value) { + mUsedInFix = value; + } + + public static final Creator<GpsMeasurement> CREATOR = new Creator<GpsMeasurement>() { + @Override + public GpsMeasurement createFromParcel(Parcel parcel) { + GpsMeasurement gpsMeasurement = new GpsMeasurement(); + + gpsMeasurement.mFlags = parcel.readInt(); + gpsMeasurement.mPrn = parcel.readByte(); + gpsMeasurement.mTimeOffsetInNs = parcel.readDouble(); + gpsMeasurement.mState = (short) parcel.readInt(); + gpsMeasurement.mReceivedGpsTowInNs = parcel.readLong(); + gpsMeasurement.mReceivedGpsTowUncertaintyInNs = parcel.readLong(); + gpsMeasurement.mCn0InDbHz = parcel.readDouble(); + gpsMeasurement.mPseudorangeRateInMetersPerSec = parcel.readDouble(); + gpsMeasurement.mPseudorangeRateUncertaintyInMetersPerSec = parcel.readDouble(); + gpsMeasurement.mAccumulatedDeltaRangeState = (short) parcel.readInt(); + gpsMeasurement.mAccumulatedDeltaRangeInMeters = parcel.readDouble(); + gpsMeasurement.mAccumulatedDeltaRangeUncertaintyInMeters = parcel.readDouble(); + gpsMeasurement.mPseudorangeInMeters = parcel.readDouble(); + gpsMeasurement.mPseudorangeUncertaintyInMeters = parcel.readDouble(); + gpsMeasurement.mCodePhaseInChips = parcel.readDouble(); + gpsMeasurement.mCodePhaseUncertaintyInChips = parcel.readDouble(); + gpsMeasurement.mCarrierFrequencyInHz = parcel.readFloat(); + gpsMeasurement.mCarrierCycles = parcel.readLong(); + gpsMeasurement.mCarrierPhase = parcel.readDouble(); + gpsMeasurement.mCarrierPhaseUncertainty = parcel.readDouble(); + gpsMeasurement.mLossOfLock = parcel.readByte(); + gpsMeasurement.mBitNumber = parcel.readInt(); + gpsMeasurement.mTimeFromLastBitInMs = (short) parcel.readInt(); + gpsMeasurement.mDopplerShiftInHz = parcel.readDouble(); + gpsMeasurement.mDopplerShiftUncertaintyInHz = parcel.readDouble(); + gpsMeasurement.mMultipathIndicator = parcel.readByte(); + gpsMeasurement.mSnrInDb = parcel.readDouble(); + gpsMeasurement.mElevationInDeg = parcel.readDouble(); + gpsMeasurement.mElevationUncertaintyInDeg = parcel.readDouble(); + gpsMeasurement.mAzimuthInDeg = parcel.readDouble(); + gpsMeasurement.mAzimuthUncertaintyInDeg = parcel.readDouble(); + gpsMeasurement.mUsedInFix = parcel.readInt() != 0; + + return gpsMeasurement; + } + + @Override + public GpsMeasurement[] newArray(int i) { + return new GpsMeasurement[i]; + } + }; + + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mFlags); + parcel.writeByte(mPrn); + parcel.writeDouble(mTimeOffsetInNs); + parcel.writeInt(mState); + parcel.writeLong(mReceivedGpsTowInNs); + parcel.writeLong(mReceivedGpsTowUncertaintyInNs); + parcel.writeDouble(mCn0InDbHz); + parcel.writeDouble(mPseudorangeRateInMetersPerSec); + parcel.writeDouble(mPseudorangeRateUncertaintyInMetersPerSec); + parcel.writeInt(mAccumulatedDeltaRangeState); + parcel.writeDouble(mAccumulatedDeltaRangeInMeters); + parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyInMeters); + parcel.writeDouble(mPseudorangeInMeters); + parcel.writeDouble(mPseudorangeUncertaintyInMeters); + parcel.writeDouble(mCodePhaseInChips); + parcel.writeDouble(mCodePhaseUncertaintyInChips); + parcel.writeFloat(mCarrierFrequencyInHz); + parcel.writeLong(mCarrierCycles); + parcel.writeDouble(mCarrierPhase); + parcel.writeDouble(mCarrierPhaseUncertainty); + parcel.writeByte(mLossOfLock); + parcel.writeInt(mBitNumber); + parcel.writeInt(mTimeFromLastBitInMs); + parcel.writeDouble(mDopplerShiftInHz); + parcel.writeDouble(mDopplerShiftUncertaintyInHz); + parcel.writeByte(mMultipathIndicator); + parcel.writeDouble(mSnrInDb); + parcel.writeDouble(mElevationInDeg); + parcel.writeDouble(mElevationUncertaintyInDeg); + parcel.writeDouble(mAzimuthInDeg); + parcel.writeDouble(mAzimuthUncertaintyInDeg); + parcel.writeInt(mUsedInFix ? 1 : 0); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + final String format = " %-29s = %s\n"; + final String formatWithUncertainty = " %-29s = %-25s %-40s = %s\n"; + StringBuilder builder = new StringBuilder("GpsMeasurement:\n"); + + builder.append(String.format(format, "Prn", mPrn)); + + builder.append(String.format(format, "TimeOffsetInNs", mTimeOffsetInNs)); + + builder.append(String.format(format, "State", getStateString())); + + builder.append(String.format( + formatWithUncertainty, + "ReceivedGpsTowInNs", + mReceivedGpsTowInNs, + "ReceivedGpsTowUncertaintyInNs", + mReceivedGpsTowUncertaintyInNs)); + + builder.append(String.format(format, "Cn0InDbHz", mCn0InDbHz)); + + builder.append(String.format( + formatWithUncertainty, + "PseudorangeRateInMetersPerSec", + mPseudorangeRateInMetersPerSec, + "PseudorangeRateUncertaintyInMetersPerSec", + mPseudorangeRateUncertaintyInMetersPerSec)); + + builder.append(String.format( + format, + "AccumulatedDeltaRangeState", + getAccumulatedDeltaRangeStateString())); + + builder.append(String.format( + formatWithUncertainty, + "AccumulatedDeltaRangeInMeters", + mAccumulatedDeltaRangeInMeters, + "AccumulatedDeltaRangeUncertaintyInMeters", + mAccumulatedDeltaRangeUncertaintyInMeters)); + + builder.append(String.format( + formatWithUncertainty, + "PseudorangeInMeters", + hasPseudorangeInMeters() ? mPseudorangeInMeters : null, + "PseudorangeUncertaintyInMeters", + hasPseudorangeUncertaintyInMeters() ? mPseudorangeUncertaintyInMeters : null)); + + builder.append(String.format( + formatWithUncertainty, + "CodePhaseInChips", + hasCodePhaseInChips() ? mCodePhaseInChips : null, + "CodePhaseUncertaintyInChips", + hasCodePhaseUncertaintyInChips() ? mCodePhaseUncertaintyInChips : null)); + + builder.append(String.format( + format, + "CarrierFrequencyInHz", + hasCarrierFrequencyInHz() ? mCarrierFrequencyInHz : null)); + + builder.append(String.format( + format, + "CarrierCycles", + hasCarrierCycles() ? mCarrierCycles : null)); + + builder.append(String.format( + formatWithUncertainty, + "CarrierPhase", + hasCarrierPhase() ? mCarrierPhase : null, + "CarrierPhaseUncertainty", + hasCarrierPhaseUncertainty() ? mCarrierPhaseUncertainty : null)); + + builder.append(String.format(format, "LossOfLock", getLossOfLockString())); + + builder.append(String.format( + format, + "BitNumber", + hasBitNumber() ? mBitNumber : null)); + + builder.append(String.format( + format, + "TimeFromLastBitInMs", + hasTimeFromLastBitInMs() ? mTimeFromLastBitInMs : null)); + + builder.append(String.format( + formatWithUncertainty, + "DopplerShiftInHz", + hasDopplerShiftInHz() ? mDopplerShiftInHz : null, + "DopplerShiftUncertaintyInHz", + hasDopplerShiftUncertaintyInHz() ? mDopplerShiftUncertaintyInHz : null)); + + builder.append(String.format(format, "MultipathIndicator", getMultipathIndicatorString())); + + builder.append(String.format( + format, + "SnrInDb", + hasSnrInDb() ? mSnrInDb : null)); + + builder.append(String.format( + formatWithUncertainty, + "ElevationInDeg", + hasElevationInDeg() ? mElevationInDeg : null, + "ElevationUncertaintyInDeg", + hasElevationUncertaintyInDeg() ? mElevationUncertaintyInDeg : null)); + + builder.append(String.format( + formatWithUncertainty, + "AzimuthInDeg", + hasAzimuthInDeg() ? mAzimuthInDeg : null, + "AzimuthUncertaintyInDeg", + hasAzimuthUncertaintyInDeg() ? mAzimuthUncertaintyInDeg : null)); + + builder.append(String.format(format, "UsedInFix", mUsedInFix)); + + return builder.toString(); + } + + private void initialize() { + mFlags = HAS_NO_FLAGS; + setPrn(Byte.MIN_VALUE); + setTimeOffsetInNs(Long.MIN_VALUE); + setState(STATE_UNKNOWN); + setReceivedGpsTowInNs(Long.MIN_VALUE); + setReceivedGpsTowUncertaintyInNs(Long.MAX_VALUE); + setCn0InDbHz(Double.MIN_VALUE); + setPseudorangeRateInMetersPerSec(Double.MIN_VALUE); + setPseudorangeRateUncertaintyInMetersPerSec(Double.MIN_VALUE); + setAccumulatedDeltaRangeState(ADR_STATE_UNKNOWN); + setAccumulatedDeltaRangeInMeters(Double.MIN_VALUE); + setAccumulatedDeltaRangeUncertaintyInMeters(Double.MIN_VALUE); + resetPseudorangeInMeters(); + resetPseudorangeUncertaintyInMeters(); + resetCodePhaseInChips(); + resetCodePhaseUncertaintyInChips(); + resetCarrierFrequencyInHz(); + resetCarrierCycles(); + resetCarrierPhase(); + resetCarrierPhaseUncertainty(); + setLossOfLock(LOSS_OF_LOCK_UNKNOWN); + resetBitNumber(); + resetTimeFromLastBitInMs(); + resetDopplerShiftInHz(); + resetDopplerShiftUncertaintyInHz(); + setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN); + resetSnrInDb(); + resetElevationInDeg(); + resetElevationUncertaintyInDeg(); + resetAzimuthInDeg(); + resetAzimuthUncertaintyInDeg(); + setUsedInFix(false); + } + + private void setFlag(int flag) { + mFlags |= flag; + } + + private void resetFlag(int flag) { + mFlags &= ~flag; + } + + private boolean isFlagSet(int flag) { + return (mFlags & flag) == flag; + } +} |