diff options
| author | 2016-02-02 17:25:32 -0800 | |
|---|---|---|
| committer | 2016-02-02 17:25:32 -0800 | |
| commit | d46d308562b78af6a06d014e17cb67a6e3103b30 (patch) | |
| tree | 255846f65e8fa569e35da9cc797d0efc34b8cfce | |
| parent | 818aa2c2c46addae934fb6cd42f889affc9ef747 (diff) | |
Worked around the crash caused by API renaming
Bug: 26885642
Change-Id: I1f1ad76d18444d5f250397ef491e1dd4858f0a1d
| -rw-r--r-- | api/system-current.txt | 229 | ||||
| -rw-r--r-- | location/java/android/location/GpsClock.java | 503 | ||||
| -rw-r--r-- | location/java/android/location/GpsMeasurement.java | 1413 | ||||
| -rw-r--r-- | location/java/android/location/GpsMeasurementsEvent.java | 159 | ||||
| -rw-r--r-- | location/java/android/location/GpsNavigationMessage.java | 324 | ||||
| -rw-r--r-- | location/java/android/location/GpsNavigationMessageEvent.java | 119 | ||||
| -rw-r--r-- | location/java/android/location/LocationManager.java | 48 |
7 files changed, 2794 insertions, 1 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 3c39cb13fbaa..f42252f5f9c6 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -20574,6 +20574,231 @@ package android.location { method public void onStopped(); } + public class GpsClock implements android.os.Parcelable { + method public int describeContents(); + method public double getBiasInNs(); + method public double getBiasUncertaintyInNs(); + method public double getDriftInNsPerSec(); + method public double getDriftUncertaintyInNsPerSec(); + method public long getFullBiasInNs(); + method public short getLeapSecond(); + method public long getTimeInNs(); + method public double getTimeUncertaintyInNs(); + method public byte getType(); + method public boolean hasBiasInNs(); + method public boolean hasBiasUncertaintyInNs(); + method public boolean hasDriftInNsPerSec(); + method public boolean hasDriftUncertaintyInNsPerSec(); + method public boolean hasFullBiasInNs(); + method public boolean hasLeapSecond(); + method public boolean hasTimeUncertaintyInNs(); + method public void reset(); + method public void resetBiasInNs(); + method public void resetBiasUncertaintyInNs(); + method public void resetDriftInNsPerSec(); + method public void resetDriftUncertaintyInNsPerSec(); + method public void resetFullBiasInNs(); + method public void resetLeapSecond(); + method public void resetTimeUncertaintyInNs(); + method public void set(android.location.GpsClock); + method public void setBiasInNs(double); + method public void setBiasUncertaintyInNs(double); + method public void setDriftInNsPerSec(double); + method public void setDriftUncertaintyInNsPerSec(double); + method public void setFullBiasInNs(long); + method public void setLeapSecond(short); + method public void setTimeInNs(long); + method public void setTimeUncertaintyInNs(double); + method public void setType(byte); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR; + field public static final byte TYPE_GPS_TIME = 2; // 0x2 + field public static final byte TYPE_LOCAL_HW_TIME = 1; // 0x1 + field public static final byte TYPE_UNKNOWN = 0; // 0x0 + } + + public class GpsMeasurement implements android.os.Parcelable { + method public int describeContents(); + method public double getAccumulatedDeltaRangeInMeters(); + method public short getAccumulatedDeltaRangeState(); + method public double getAccumulatedDeltaRangeUncertaintyInMeters(); + method public double getAzimuthInDeg(); + method public double getAzimuthUncertaintyInDeg(); + method public int getBitNumber(); + method public long getCarrierCycles(); + method public float getCarrierFrequencyInHz(); + method public double getCarrierPhase(); + method public double getCarrierPhaseUncertainty(); + method public double getCn0InDbHz(); + method public double getCodePhaseInChips(); + method public double getCodePhaseUncertaintyInChips(); + method public double getDopplerShiftInHz(); + method public double getDopplerShiftUncertaintyInHz(); + method public double getElevationInDeg(); + method public double getElevationUncertaintyInDeg(); + method public byte getLossOfLock(); + method public byte getMultipathIndicator(); + method public byte getPrn(); + method public double getPseudorangeInMeters(); + method public double getPseudorangeRateInMetersPerSec(); + method public double getPseudorangeRateUncertaintyInMetersPerSec(); + method public double getPseudorangeUncertaintyInMeters(); + method public long getReceivedGpsTowInNs(); + method public long getReceivedGpsTowUncertaintyInNs(); + method public double getSnrInDb(); + method public short getState(); + method public short getTimeFromLastBitInMs(); + method public double getTimeOffsetInNs(); + method public boolean hasAzimuthInDeg(); + method public boolean hasAzimuthUncertaintyInDeg(); + method public boolean hasBitNumber(); + method public boolean hasCarrierCycles(); + method public boolean hasCarrierFrequencyInHz(); + method public boolean hasCarrierPhase(); + method public boolean hasCarrierPhaseUncertainty(); + method public boolean hasCodePhaseInChips(); + method public boolean hasCodePhaseUncertaintyInChips(); + method public boolean hasDopplerShiftInHz(); + method public boolean hasDopplerShiftUncertaintyInHz(); + method public boolean hasElevationInDeg(); + method public boolean hasElevationUncertaintyInDeg(); + method public boolean hasPseudorangeInMeters(); + method public boolean hasPseudorangeUncertaintyInMeters(); + method public boolean hasSnrInDb(); + method public boolean hasTimeFromLastBitInMs(); + method public boolean isPseudorangeRateCorrected(); + method public boolean isUsedInFix(); + method public void reset(); + method public void resetAzimuthInDeg(); + method public void resetAzimuthUncertaintyInDeg(); + method public void resetBitNumber(); + method public void resetCarrierCycles(); + method public void resetCarrierFrequencyInHz(); + method public void resetCarrierPhase(); + method public void resetCarrierPhaseUncertainty(); + method public void resetCodePhaseInChips(); + method public void resetCodePhaseUncertaintyInChips(); + method public void resetDopplerShiftInHz(); + method public void resetDopplerShiftUncertaintyInHz(); + method public void resetElevationInDeg(); + method public void resetElevationUncertaintyInDeg(); + method public void resetPseudorangeInMeters(); + method public void resetPseudorangeUncertaintyInMeters(); + method public void resetSnrInDb(); + method public void resetTimeFromLastBitInMs(); + method public void set(android.location.GpsMeasurement); + method public void setAccumulatedDeltaRangeInMeters(double); + method public void setAccumulatedDeltaRangeState(short); + method public void setAccumulatedDeltaRangeUncertaintyInMeters(double); + method public void setAzimuthInDeg(double); + method public void setAzimuthUncertaintyInDeg(double); + method public void setBitNumber(int); + method public void setCarrierCycles(long); + method public void setCarrierFrequencyInHz(float); + method public void setCarrierPhase(double); + method public void setCarrierPhaseUncertainty(double); + method public void setCn0InDbHz(double); + method public void setCodePhaseInChips(double); + method public void setCodePhaseUncertaintyInChips(double); + method public void setDopplerShiftInHz(double); + method public void setDopplerShiftUncertaintyInHz(double); + method public void setElevationInDeg(double); + method public void setElevationUncertaintyInDeg(double); + method public void setLossOfLock(byte); + method public void setMultipathIndicator(byte); + method public void setPrn(byte); + method public void setPseudorangeInMeters(double); + method public void setPseudorangeRateInMetersPerSec(double); + method public void setPseudorangeRateUncertaintyInMetersPerSec(double); + method public void setPseudorangeUncertaintyInMeters(double); + method public void setReceivedGpsTowInNs(long); + method public void setReceivedGpsTowUncertaintyInNs(long); + method public void setSnrInDb(double); + method public void setState(short); + method public void setTimeFromLastBitInMs(short); + method public void setTimeOffsetInNs(double); + method public void setUsedInFix(boolean); + method public void writeToParcel(android.os.Parcel, int); + field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4 + field public static final short ADR_STATE_RESET = 2; // 0x2 + field public static final short ADR_STATE_UNKNOWN = 0; // 0x0 + field public static final short ADR_STATE_VALID = 1; // 0x1 + field public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR; + field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2 + field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1 + field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0 + field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1 + field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2 + field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0 + field public static final short STATE_BIT_SYNC = 2; // 0x2 + field public static final short STATE_CODE_LOCK = 1; // 0x1 + field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10 + field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4 + field public static final short STATE_TOW_DECODED = 8; // 0x8 + field public static final short STATE_UNKNOWN = 0; // 0x0 + } + + public class GpsMeasurementsEvent implements android.os.Parcelable { + ctor public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]); + method public int describeContents(); + method public android.location.GpsClock getClock(); + method public java.util.Collection<android.location.GpsMeasurement> getMeasurements(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.location.GpsMeasurementsEvent> CREATOR; + field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2 + field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0 + field public static final int STATUS_READY = 1; // 0x1 + } + + public static abstract interface GpsMeasurementsEvent.Listener { + method public abstract void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent); + method public abstract void onStatusChanged(int); + } + + public class GpsNavigationMessage implements android.os.Parcelable { + method public int describeContents(); + method public byte[] getData(); + method public short getMessageId(); + method public byte getPrn(); + method public short getStatus(); + method public short getSubmessageId(); + method public byte getType(); + method public void reset(); + method public void set(android.location.GpsNavigationMessage); + method public void setData(byte[]); + method public void setMessageId(short); + method public void setPrn(byte); + method public void setStatus(short); + method public void setSubmessageId(short); + method public void setType(byte); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR; + field public static final short STATUS_PARITY_PASSED = 1; // 0x1 + field public static final short STATUS_PARITY_REBUILT = 2; // 0x2 + field public static final short STATUS_UNKNOWN = 0; // 0x0 + field public static final byte TYPE_CNAV2 = 4; // 0x4 + field public static final byte TYPE_L1CA = 1; // 0x1 + field public static final byte TYPE_L2CNAV = 2; // 0x2 + field public static final byte TYPE_L5CNAV = 3; // 0x3 + field public static final byte TYPE_UNKNOWN = 0; // 0x0 + } + + public class GpsNavigationMessageEvent implements android.os.Parcelable { + ctor public GpsNavigationMessageEvent(android.location.GpsNavigationMessage); + method public int describeContents(); + method public android.location.GpsNavigationMessage getNavigationMessage(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR; + field public static int STATUS_GPS_LOCATION_DISABLED; + field public static int STATUS_NOT_SUPPORTED; + field public static int STATUS_READY; + } + + public static abstract interface GpsNavigationMessageEvent.Listener { + method public abstract void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent); + method public abstract void onStatusChanged(int); + } + public final class GpsSatellite { method public float getAzimuth(); method public float getElevation(); @@ -20678,6 +20903,8 @@ package android.location { } public class LocationManager { + method public deprecated boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener); + method public deprecated boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener); method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener); method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener); method public boolean addNmeaListener(android.location.GnssNmeaListener); @@ -20701,6 +20928,8 @@ package android.location { method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler); method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback); method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler); + method public deprecated void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener); + method public deprecated void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener); method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener); method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener); method public void removeNmeaListener(android.location.GnssNmeaListener); diff --git a/location/java/android/location/GpsClock.java b/location/java/android/location/GpsClock.java new file mode 100644 index 000000000000..4135a1c949bb --- /dev/null +++ b/location/java/android/location/GpsClock.java @@ -0,0 +1,503 @@ +/* + * 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.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A class containing a GPS clock timestamp. + * It represents a measurement of the GPS receiver's clock. + * + * @hide + */ +@SystemApi +public class GpsClock implements Parcelable { + + // The following enumerations must be in sync with the values declared in gps.h + + /** + * The type of the time stored is not available or it is unknown. + */ + public static final byte TYPE_UNKNOWN = 0; + + /** + * The source of the time value reported by this class is the 'Local Hardware Clock'. + */ + public static final byte TYPE_LOCAL_HW_TIME = 1; + + /** + * The source of the time value reported by this class is the 'GPS time' derived from + * satellites (epoch = Jan 6, 1980). + */ + public static final byte TYPE_GPS_TIME = 2; + + private static final short HAS_NO_FLAGS = 0; + private static final short HAS_LEAP_SECOND = (1<<0); + private static final short HAS_TIME_UNCERTAINTY = (1<<1); + private static final short HAS_FULL_BIAS = (1<<2); + private static final short HAS_BIAS = (1<<3); + private static final short HAS_BIAS_UNCERTAINTY = (1<<4); + private static final short HAS_DRIFT = (1<<5); + private static final short HAS_DRIFT_UNCERTAINTY = (1<<6); + + // End enumerations in sync with gps.h + + private short mFlags; + private short mLeapSecond; + private byte mType; + private long mTimeInNs; + private double mTimeUncertaintyInNs; + private long mFullBiasInNs; + private double mBiasInNs; + private double mBiasUncertaintyInNs; + private double mDriftInNsPerSec; + private double mDriftUncertaintyInNsPerSec; + + GpsClock() { + initialize(); + } + + /** + * Sets all contents to the values stored in the provided object. + */ + public void set(GpsClock clock) { + mFlags = clock.mFlags; + mLeapSecond = clock.mLeapSecond; + mType = clock.mType; + mTimeInNs = clock.mTimeInNs; + mTimeUncertaintyInNs = clock.mTimeUncertaintyInNs; + mFullBiasInNs = clock.mFullBiasInNs; + mBiasInNs = clock.mBiasInNs; + mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs; + mDriftInNsPerSec = clock.mDriftInNsPerSec; + mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec; + } + + /** + * Resets all the contents to its original state. + */ + public void reset() { + initialize(); + } + + /** + * Gets the type of time reported by {@link #getTimeInNs()}. + */ + public byte getType() { + return mType; + } + + /** + * Sets the type of time reported. + */ + public void setType(byte value) { + mType = value; + } + + /** + * Gets a string representation of the 'type'. + * For internal and logging use only. + */ + private String getTypeString() { + switch (mType) { + case TYPE_UNKNOWN: + return "Unknown"; + case TYPE_GPS_TIME: + return "GpsTime"; + case TYPE_LOCAL_HW_TIME: + return "LocalHwClock"; + default: + return "<Invalid:" + mType + ">"; + } + } + + /** + * Returns true if {@link #getLeapSecond()} is available, false otherwise. + */ + public boolean hasLeapSecond() { + return isFlagSet(HAS_LEAP_SECOND); + } + + /** + * Gets the leap second associated with the clock's time. + * The sign of the value is defined by the following equation: + * utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000 + * + * The value is only available if {@link #hasLeapSecond()} is true. + */ + public short getLeapSecond() { + return mLeapSecond; + } + + /** + * Sets the leap second associated with the clock's time. + */ + public void setLeapSecond(short leapSecond) { + setFlag(HAS_LEAP_SECOND); + mLeapSecond = leapSecond; + } + + /** + * Resets the leap second associated with the clock's time. + */ + public void resetLeapSecond() { + resetFlag(HAS_LEAP_SECOND); + mLeapSecond = Short.MIN_VALUE; + } + + /** + * Gets the GPS receiver internal clock value in nanoseconds. + * This can be either the 'local hardware clock' value ({@link #TYPE_LOCAL_HW_TIME}), or the + * current GPS time derived inside GPS receiver ({@link #TYPE_GPS_TIME}). + * {@link #getType()} defines the time reported. + * + * For 'local hardware clock' this value is expected to be monotonically increasing during the + * reporting session. The real GPS time can be derived by compensating + * {@link #getFullBiasInNs()} (when it is available) from this value. + * + * For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS + * receiver can achieve. {@link #getTimeUncertaintyInNs()} should be available when GPS time is + * specified. + * + * Sub-nanosecond accuracy can be provided by means of {@link #getBiasInNs()}. + * The reported time includes {@link #getTimeUncertaintyInNs()}. + */ + public long getTimeInNs() { + return mTimeInNs; + } + + /** + * Sets the GPS receiver internal clock in nanoseconds. + */ + public void setTimeInNs(long timeInNs) { + mTimeInNs = timeInNs; + } + + /** + * Returns true if {@link #getTimeUncertaintyInNs()} is available, false otherwise. + */ + public boolean hasTimeUncertaintyInNs() { + return isFlagSet(HAS_TIME_UNCERTAINTY); + } + + /** + * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds. + * The uncertainty is represented as an absolute (single sided) value. + * + * The value is only available if {@link #hasTimeUncertaintyInNs()} is true. + */ + public double getTimeUncertaintyInNs() { + return mTimeUncertaintyInNs; + } + + /** + * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds. + */ + public void setTimeUncertaintyInNs(double timeUncertaintyInNs) { + setFlag(HAS_TIME_UNCERTAINTY); + mTimeUncertaintyInNs = timeUncertaintyInNs; + } + + /** + * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds. + */ + public void resetTimeUncertaintyInNs() { + resetFlag(HAS_TIME_UNCERTAINTY); + mTimeUncertaintyInNs = Double.NaN; + } + + /** + * Returns true if {@link @getFullBiasInNs()} is available, false otherwise. + */ + public boolean hasFullBiasInNs() { + return isFlagSet(HAS_FULL_BIAS); + } + + /** + * Gets the difference between hardware clock ({@link #getTimeInNs()}) inside GPS receiver and + * the true GPS time since 0000Z, January 6, 1980, in nanoseconds. + * + * This value is available if {@link #TYPE_LOCAL_HW_TIME} is set, and GPS receiver has solved + * the clock for GPS time. + * {@link #getBiasUncertaintyInNs()} should be used for quality check. + * + * The sign of the value is defined by the following equation: + * true time (GPS time) = time_ns + (full_bias_ns + bias_ns) + * + * The reported full bias includes {@link #getBiasUncertaintyInNs()}. + * The value is onl available if {@link #hasFullBiasInNs()} is true. + */ + public long getFullBiasInNs() { + return mFullBiasInNs; + } + + /** + * Sets the full bias in nanoseconds. + */ + public void setFullBiasInNs(long value) { + setFlag(HAS_FULL_BIAS); + mFullBiasInNs = value; + } + + /** + * Resets the full bias in nanoseconds. + */ + public void resetFullBiasInNs() { + resetFlag(HAS_FULL_BIAS); + mFullBiasInNs = Long.MIN_VALUE; + } + + /** + * Returns true if {@link #getBiasInNs()} is available, false otherwise. + */ + public boolean hasBiasInNs() { + return isFlagSet(HAS_BIAS); + } + + /** + * Gets the clock's sub-nanosecond bias. + * The reported bias includes {@link #getBiasUncertaintyInNs()}. + * + * The value is only available if {@link #hasBiasInNs()} is true. + */ + public double getBiasInNs() { + return mBiasInNs; + } + + /** + * Sets the sub-nanosecond bias. + */ + public void setBiasInNs(double biasInNs) { + setFlag(HAS_BIAS); + mBiasInNs = biasInNs; + } + + /** + * Resets the clock's Bias in nanoseconds. + */ + public void resetBiasInNs() { + resetFlag(HAS_BIAS); + mBiasInNs = Double.NaN; + } + + /** + * Returns true if {@link #getBiasUncertaintyInNs()} is available, false otherwise. + */ + public boolean hasBiasUncertaintyInNs() { + return isFlagSet(HAS_BIAS_UNCERTAINTY); + } + + /** + * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds. + * + * The value is only available if {@link #hasBiasUncertaintyInNs()} is true. + */ + public double getBiasUncertaintyInNs() { + return mBiasUncertaintyInNs; + } + + /** + * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds. + */ + public void setBiasUncertaintyInNs(double biasUncertaintyInNs) { + setFlag(HAS_BIAS_UNCERTAINTY); + mBiasUncertaintyInNs = biasUncertaintyInNs; + } + + /** + * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds. + */ + public void resetBiasUncertaintyInNs() { + resetFlag(HAS_BIAS_UNCERTAINTY); + mBiasUncertaintyInNs = Double.NaN; + } + + /** + * Returns true if {@link #getDriftInNsPerSec()} is available, false otherwise. + */ + public boolean hasDriftInNsPerSec() { + return isFlagSet(HAS_DRIFT); + } + + /** + * Gets the clock's Drift in nanoseconds per second. + * A positive value indicates that the frequency is higher than the nominal frequency. + * The reported drift includes {@link #getDriftUncertaintyInNsPerSec()}. + * + * The value is only available if {@link #hasDriftInNsPerSec()} is true. + */ + public double getDriftInNsPerSec() { + return mDriftInNsPerSec; + } + + /** + * Sets the clock's Drift in nanoseconds per second. + */ + public void setDriftInNsPerSec(double driftInNsPerSec) { + setFlag(HAS_DRIFT); + mDriftInNsPerSec = driftInNsPerSec; + } + + /** + * Resets the clock's Drift in nanoseconds per second. + */ + public void resetDriftInNsPerSec() { + resetFlag(HAS_DRIFT); + mDriftInNsPerSec = Double.NaN; + } + + /** + * Returns true if {@link #getDriftUncertaintyInNsPerSec()} is available, false otherwise. + */ + public boolean hasDriftUncertaintyInNsPerSec() { + return isFlagSet(HAS_DRIFT_UNCERTAINTY); + } + + /** + * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second. + * + * The value is only available if {@link #hasDriftUncertaintyInNsPerSec()} is true. + */ + public double getDriftUncertaintyInNsPerSec() { + return mDriftUncertaintyInNsPerSec; + } + + /** + * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second. + */ + public void setDriftUncertaintyInNsPerSec(double driftUncertaintyInNsPerSec) { + setFlag(HAS_DRIFT_UNCERTAINTY); + mDriftUncertaintyInNsPerSec = driftUncertaintyInNsPerSec; + } + + /** + * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second. + */ + public void resetDriftUncertaintyInNsPerSec() { + resetFlag(HAS_DRIFT_UNCERTAINTY); + mDriftUncertaintyInNsPerSec = Double.NaN; + } + + public static final Creator<GpsClock> CREATOR = new Creator<GpsClock>() { + @Override + public GpsClock createFromParcel(Parcel parcel) { + GpsClock gpsClock = new GpsClock(); + + gpsClock.mFlags = (short) parcel.readInt(); + gpsClock.mLeapSecond = (short) parcel.readInt(); + gpsClock.mType = parcel.readByte(); + gpsClock.mTimeInNs = parcel.readLong(); + gpsClock.mTimeUncertaintyInNs = parcel.readDouble(); + gpsClock.mFullBiasInNs = parcel.readLong(); + gpsClock.mBiasInNs = parcel.readDouble(); + gpsClock.mBiasUncertaintyInNs = parcel.readDouble(); + gpsClock.mDriftInNsPerSec = parcel.readDouble(); + gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble(); + + return gpsClock; + } + + @Override + public GpsClock[] newArray(int size) { + return new GpsClock[size]; + } + }; + + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mFlags); + parcel.writeInt(mLeapSecond); + parcel.writeByte(mType); + parcel.writeLong(mTimeInNs); + parcel.writeDouble(mTimeUncertaintyInNs); + parcel.writeLong(mFullBiasInNs); + parcel.writeDouble(mBiasInNs); + parcel.writeDouble(mBiasUncertaintyInNs); + parcel.writeDouble(mDriftInNsPerSec); + parcel.writeDouble(mDriftUncertaintyInNsPerSec); + } + + @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("GpsClock:\n"); + + builder.append(String.format(format, "Type", getTypeString())); + + builder.append(String.format(format, "LeapSecond", hasLeapSecond() ? mLeapSecond : null)); + + builder.append(String.format( + formatWithUncertainty, + "TimeInNs", + mTimeInNs, + "TimeUncertaintyInNs", + hasTimeUncertaintyInNs() ? mTimeUncertaintyInNs : null)); + + builder.append(String.format( + format, + "FullBiasInNs", + hasFullBiasInNs() ? mFullBiasInNs : null)); + + builder.append(String.format( + formatWithUncertainty, + "BiasInNs", + hasBiasInNs() ? mBiasInNs : null, + "BiasUncertaintyInNs", + hasBiasUncertaintyInNs() ? mBiasUncertaintyInNs : null)); + + builder.append(String.format( + formatWithUncertainty, + "DriftInNsPerSec", + hasDriftInNsPerSec() ? mDriftInNsPerSec : null, + "DriftUncertaintyInNsPerSec", + hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null)); + + return builder.toString(); + } + + private void initialize() { + mFlags = HAS_NO_FLAGS; + resetLeapSecond(); + setType(TYPE_UNKNOWN); + setTimeInNs(Long.MIN_VALUE); + resetTimeUncertaintyInNs(); + resetFullBiasInNs(); + resetBiasInNs(); + resetBiasUncertaintyInNs(); + resetDriftInNsPerSec(); + resetDriftUncertaintyInNsPerSec(); + } + + private void setFlag(short flag) { + mFlags |= flag; + } + + private void resetFlag(short flag) { + mFlags &= ~flag; + } + + private boolean isFlagSet(short flag) { + return (mFlags & flag) == flag; + } +} diff --git a/location/java/android/location/GpsMeasurement.java b/location/java/android/location/GpsMeasurement.java new file mode 100644 index 000000000000..f13a440f411a --- /dev/null +++ b/location/java/android/location/GpsMeasurement.java @@ -0,0 +1,1413 @@ +/* + * 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.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A class representing a GPS satellite measurement, containing raw and computed information. + * + * @hide + */ +@SystemApi +public class GpsMeasurement implements Parcelable { + 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); + private static final int HAS_USED_IN_FIX = (1<<17); + private static final int GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18); + + /** + * 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 GPS receiver contains millisecond ambiguity. + */ + public static final short STATE_MSEC_AMBIGUOUS = (1<<4); + + /** + * All the GPS receiver state flags. + */ + private static final short STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC + | STATE_TOW_DECODED | STATE_MSEC_AMBIGUOUS; + + /** + * 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); + + /** + * All the 'Accumulated Delta Range' flags. + */ + private static final short ADR_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP; + + // 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) { + mState = value; + } + + /** + * Gets a string representation of the 'sync state'. + * For internal and logging use only. + */ + private String getStateString() { + if (mState == STATE_UNKNOWN) { + return "Unknown"; + } + StringBuilder builder = new StringBuilder(); + if ((mState & STATE_CODE_LOCK) == STATE_CODE_LOCK) { + builder.append("CodeLock|"); + } + if ((mState & STATE_BIT_SYNC) == STATE_BIT_SYNC) { + builder.append("BitSync|"); + } + if ((mState & STATE_SUBFRAME_SYNC) == STATE_SUBFRAME_SYNC) { + builder.append("SubframeSync|"); + } + if ((mState & STATE_TOW_DECODED) == STATE_TOW_DECODED) { + builder.append("TowDecoded|"); + } + if ((mState & STATE_MSEC_AMBIGUOUS) == STATE_MSEC_AMBIGUOUS) { + builder.append("MsecAmbiguous"); + } + int remainingStates = mState & ~STATE_ALL; + if (remainingStates > 0) { + builder.append("Other("); + builder.append(Integer.toBinaryString(remainingStates)); + builder.append(")|"); + } + builder.deleteCharAt(builder.length() - 1); + return builder.toString(); + } + + /** + * 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()}. + * + * The correction of a given Pseudorange Rate value includes corrections from receiver and + * satellite clock frequency errors. + * {@link #isPseudorangeRateCorrected()} identifies the type of value reported. + * + * A positive 'uncorrected' value indicates that the SV is moving away from the receiver. + * The sign of the 'uncorrected' Pseudorange Rate and its relation to the sign of + * {@link #getDopplerShiftInHz()} is given by the equation: + * pseudorange rate = -k * doppler shift (where k is a constant) + */ + public double getPseudorangeRateInMetersPerSec() { + return mPseudorangeRateInMetersPerSec; + } + + /** + * Sets the pseudorange rate at the timestamp in m/s. + */ + public void setPseudorangeRateInMetersPerSec(double value) { + mPseudorangeRateInMetersPerSec = value; + } + + /** + * See {@link #getPseudorangeRateInMetersPerSec()} for more details. + * + * @return {@code true} if {@link #getPseudorangeRateInMetersPerSec()} contains a corrected + * value, {@code false} if it contains an uncorrected value. + */ + public boolean isPseudorangeRateCorrected() { + return !isFlagSet(GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE); + } + + /** + * 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) { + mAccumulatedDeltaRangeState = value; + } + + /** + * Gets a string representation of the 'Accumulated Delta Range state'. + * For internal and logging use only. + */ + private String getAccumulatedDeltaRangeStateString() { + if (mAccumulatedDeltaRangeState == ADR_STATE_UNKNOWN) { + return "Unknown"; + } + StringBuilder builder = new StringBuilder(); + if ((mAccumulatedDeltaRangeState & ADR_STATE_VALID) == ADR_STATE_VALID) { + builder.append("Valid|"); + } + if ((mAccumulatedDeltaRangeState & ADR_STATE_RESET) == ADR_STATE_RESET) { + builder.append("Reset|"); + } + if ((mAccumulatedDeltaRangeState & ADR_STATE_CYCLE_SLIP) == ADR_STATE_CYCLE_SLIP) { + builder.append("CycleSlip|"); + } + int remainingStates = mAccumulatedDeltaRangeState & ~ADR_ALL; + if (remainingStates > 0) { + builder.append("Other("); + builder.append(Integer.toBinaryString(remainingStates)); + builder.append(")|"); + } + builder.deleteCharAt(builder.length() - 1); + return builder.toString(); + } + + /** + * 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()}. + * + * A positive value indicates that the SV is moving away from the receiver. + * The sign of {@link #getAccumulatedDeltaRangeInMeters()} and its relation to the sign of + * {@link #getCarrierPhase()} is given by the equation: + * accumulated delta range = -k * carrier phase (where k is a constant) + */ + 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. + * + * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}. + */ + public double getAccumulatedDeltaRangeUncertaintyInMeters() { + return mAccumulatedDeltaRangeUncertaintyInMeters; + } + + /** + * Sets the accumulated delta range's uncertainty (1-sigma) in meters. + * + * The status 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) { + mLossOfLock = value; + } + + /** + * 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:" + mLossOfLock + ">"; + } + } + + /** + * 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) { + mMultipathIndicator = value; + } + + /** + * 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:" + mMultipathIndicator + ">"; + } + } + + /** + * 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, + "PseudorangeRateIsCorrected", + isPseudorangeRateCorrected())); + + 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; + } +} diff --git a/location/java/android/location/GpsMeasurementsEvent.java b/location/java/android/location/GpsMeasurementsEvent.java new file mode 100644 index 000000000000..136687337861 --- /dev/null +++ b/location/java/android/location/GpsMeasurementsEvent.java @@ -0,0 +1,159 @@ +/* + * 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.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.security.InvalidParameterException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +/** + * A class implementing a container for data associated with a measurement event. + * Events are delivered to registered instances of {@link Listener}. + * + * @hide + */ +@SystemApi +public class GpsMeasurementsEvent implements Parcelable { + + /** + * The system does not support tracking of GPS Measurements. This status will not change in the + * future. + */ + public static final int STATUS_NOT_SUPPORTED = 0; + + /** + * GPS Measurements are successfully being tracked, it will receive updates once they are + * available. + */ + public static final int STATUS_READY = 1; + + /** + * GPS provider or Location is disabled, updates will not be received until they are enabled. + */ + public static final int STATUS_GPS_LOCATION_DISABLED = 2; + + private final GpsClock mClock; + private final Collection<GpsMeasurement> mReadOnlyMeasurements; + + /** + * Used for receiving GPS satellite measurements from the GPS engine. + * Each measurement contains raw and computed data identifying a satellite. + * You can implement this interface and call {@link LocationManager#addGpsMeasurementListener}. + * + * @hide + */ + @SystemApi + public interface Listener { + + /** + * Returns the latest collected GPS Measurements. + */ + void onGpsMeasurementsReceived(GpsMeasurementsEvent eventArgs); + + /** + * Returns the latest status of the GPS Measurements sub-system. + */ + void onStatusChanged(int status); + } + + public GpsMeasurementsEvent(GpsClock clock, GpsMeasurement[] measurements) { + if (clock == null) { + throw new InvalidParameterException("Parameter 'clock' must not be null."); + } + if (measurements == null || measurements.length == 0) { + throw new InvalidParameterException( + "Parameter 'measurements' must not be null or empty."); + } + + mClock = clock; + Collection<GpsMeasurement> measurementCollection = Arrays.asList(measurements); + mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection); + } + + @NonNull + public GpsClock getClock() { + return mClock; + } + + /** + * Gets a read-only collection of measurements associated with the current event. + */ + @NonNull + public Collection<GpsMeasurement> getMeasurements() { + return mReadOnlyMeasurements; + } + + public static final Creator<GpsMeasurementsEvent> CREATOR = + new Creator<GpsMeasurementsEvent>() { + @Override + public GpsMeasurementsEvent createFromParcel(Parcel in) { + ClassLoader classLoader = getClass().getClassLoader(); + + GpsClock clock = in.readParcelable(classLoader); + + int measurementsLength = in.readInt(); + GpsMeasurement[] measurementsArray = new GpsMeasurement[measurementsLength]; + in.readTypedArray(measurementsArray, GpsMeasurement.CREATOR); + + return new GpsMeasurementsEvent(clock, measurementsArray); + } + + @Override + public GpsMeasurementsEvent[] newArray(int size) { + return new GpsMeasurementsEvent[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeParcelable(mClock, flags); + + int measurementsCount = mReadOnlyMeasurements.size(); + GpsMeasurement[] measurementsArray = + mReadOnlyMeasurements.toArray(new GpsMeasurement[measurementsCount]); + parcel.writeInt(measurementsArray.length); + parcel.writeTypedArray(measurementsArray, flags); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("[ GpsMeasurementsEvent:\n\n"); + + builder.append(mClock.toString()); + builder.append("\n"); + + for (GpsMeasurement measurement : mReadOnlyMeasurements) { + builder.append(measurement.toString()); + builder.append("\n"); + } + + builder.append("]"); + + return builder.toString(); + } +} diff --git a/location/java/android/location/GpsNavigationMessage.java b/location/java/android/location/GpsNavigationMessage.java new file mode 100644 index 000000000000..5c3c71012cdd --- /dev/null +++ b/location/java/android/location/GpsNavigationMessage.java @@ -0,0 +1,324 @@ +/* + * 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.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.security.InvalidParameterException; + +/** + * A class containing a GPS satellite Navigation Message. + * + * @hide + */ +@SystemApi +public class GpsNavigationMessage implements Parcelable { + + private static final byte[] EMPTY_ARRAY = new byte[0]; + + // The following enumerations must be in sync with the values declared in gps.h + + /** + * The type of the navigation message is not available or unknown. + */ + public static final byte TYPE_UNKNOWN = 0; + + /** + * The Navigation Message is of type L1 C/A. + */ + public static final byte TYPE_L1CA = 1; + + /** + * The Navigation Message is of type L1-CNAV. + */ + public static final byte TYPE_L2CNAV = 2; + + /** + * The Navigation Message is of type L5-CNAV. + */ + public static final byte TYPE_L5CNAV = 3; + + /** + * The Navigation Message is of type CNAV-2. + */ + public static final byte TYPE_CNAV2 = 4; + + /** + * The Navigation Message Status is 'unknown'. + */ + public static final short STATUS_UNKNOWN = 0; + + /** + * The Navigation Message was received without any parity error in its navigation words. + */ + public static final short STATUS_PARITY_PASSED = (1<<0); + + /** + * The Navigation Message was received with words that failed parity check, but the receiver was + * able to correct those words. + */ + public static final short STATUS_PARITY_REBUILT = (1<<1); + + // End enumerations in sync with gps.h + + private byte mType; + private byte mPrn; + private short mMessageId; + private short mSubmessageId; + private byte[] mData; + private short mStatus; + + GpsNavigationMessage() { + initialize(); + } + + /** + * Sets all contents to the values stored in the provided object. + */ + public void set(GpsNavigationMessage navigationMessage) { + mType = navigationMessage.mType; + mPrn = navigationMessage.mPrn; + mMessageId = navigationMessage.mMessageId; + mSubmessageId = navigationMessage.mSubmessageId; + mData = navigationMessage.mData; + mStatus = navigationMessage.mStatus; + } + + /** + * Resets all the contents to its original state. + */ + public void reset() { + initialize(); + } + + /** + * Gets the type of the navigation message contained in the object. + */ + public byte getType() { + return mType; + } + + /** + * Sets the type of the navigation message. + */ + public void setType(byte value) { + mType = value; + } + + /** + * Gets a string representation of the 'type'. + * For internal and logging use only. + */ + private String getTypeString() { + switch (mType) { + case TYPE_UNKNOWN: + return "Unknown"; + case TYPE_L1CA: + return "L1 C/A"; + case TYPE_L2CNAV: + return "L2-CNAV"; + case TYPE_L5CNAV: + return "L5-CNAV"; + case TYPE_CNAV2: + return "CNAV-2"; + default: + return "<Invalid:" + mType + ">"; + } + } + + /** + * Gets the Pseudo-random number. + * Range: [1, 32]. + */ + public byte getPrn() { + return mPrn; + } + + /** + * Sets the Pseud-random number. + */ + public void setPrn(byte value) { + mPrn = value; + } + + /** + * Gets the Message Identifier. + * It provides an index so the complete Navigation Message can be assembled. i.e. for L1 C/A + * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message. + * Subframe 1, 2, 3 does not contain a 'frame id' and this might be reported as -1. + */ + public short getMessageId() { + return mMessageId; + } + + /** + * Sets the Message Identifier. + */ + public void setMessageId(short value) { + mMessageId = value; + } + + /** + * Gets the Sub-message Identifier. + * If required by {@link #getType()}, this value contains a sub-index within the current message + * (or frame) that is being transmitted. i.e. for L1 C/A the sub-message identifier corresponds + * to the sub-frame Id of the navigation message. + */ + public short getSubmessageId() { + return mSubmessageId; + } + + /** + * Sets the Sub-message identifier. + */ + public void setSubmessageId(short value) { + mSubmessageId = value; + } + + /** + * Gets the data associated with the Navigation Message. + * The bytes (or words) specified using big endian format (MSB first). + */ + @NonNull + public byte[] getData() { + return mData; + } + + /** + * Sets the data associated with the Navigation Message. + */ + public void setData(byte[] value) { + if (value == null) { + throw new InvalidParameterException("Data must be a non-null array"); + } + + mData = value; + } + + /** + * Gets the Status of the navigation message contained in the object. + */ + public short getStatus() { + return mStatus; + } + + /** + * Sets the status of the navigation message. + */ + public void setStatus(short value) { + mStatus = value; + } + + /** + * Gets a string representation of the 'status'. + * For internal and logging use only. + */ + private String getStatusString() { + switch (mStatus) { + case STATUS_UNKNOWN: + return "Unknown"; + case STATUS_PARITY_PASSED: + return "ParityPassed"; + case STATUS_PARITY_REBUILT: + return "ParityRebuilt"; + default: + return "<Invalid:" + mStatus + ">"; + } + } + + public static final Creator<GpsNavigationMessage> CREATOR = + new Creator<GpsNavigationMessage>() { + @Override + public GpsNavigationMessage createFromParcel(Parcel parcel) { + GpsNavigationMessage navigationMessage = new GpsNavigationMessage(); + + navigationMessage.setType(parcel.readByte()); + navigationMessage.setPrn(parcel.readByte()); + navigationMessage.setMessageId((short) parcel.readInt()); + navigationMessage.setSubmessageId((short) parcel.readInt()); + + int dataLength = parcel.readInt(); + byte[] data = new byte[dataLength]; + parcel.readByteArray(data); + navigationMessage.setData(data); + + if (parcel.dataAvail() >= Integer.SIZE) { + int status = parcel.readInt(); + navigationMessage.setStatus((short) status); + } else { + navigationMessage.setStatus(STATUS_UNKNOWN); + } + + return navigationMessage; + } + + @Override + public GpsNavigationMessage[] newArray(int size) { + return new GpsNavigationMessage[size]; + } + }; + + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeByte(mType); + parcel.writeByte(mPrn); + parcel.writeInt(mMessageId); + parcel.writeInt(mSubmessageId); + parcel.writeInt(mData.length); + parcel.writeByteArray(mData); + parcel.writeInt(mStatus); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + final String format = " %-15s = %s\n"; + StringBuilder builder = new StringBuilder("GpsNavigationMessage:\n"); + + builder.append(String.format(format, "Type", getTypeString())); + builder.append(String.format(format, "Prn", mPrn)); + builder.append(String.format(format, "Status", getStatusString())); + builder.append(String.format(format, "MessageId", mMessageId)); + builder.append(String.format(format, "SubmessageId", mSubmessageId)); + + builder.append(String.format(format, "Data", "{")); + String prefix = " "; + for(byte value : mData) { + builder.append(prefix); + builder.append(value); + prefix = ", "; + } + builder.append(" }"); + + return builder.toString(); + } + + private void initialize() { + mType = TYPE_UNKNOWN; + mPrn = 0; + mMessageId = -1; + mSubmessageId = -1; + mData = EMPTY_ARRAY; + mStatus = STATUS_UNKNOWN; + } +} diff --git a/location/java/android/location/GpsNavigationMessageEvent.java b/location/java/android/location/GpsNavigationMessageEvent.java new file mode 100644 index 000000000000..bd6921c74152 --- /dev/null +++ b/location/java/android/location/GpsNavigationMessageEvent.java @@ -0,0 +1,119 @@ +/* + * 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.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.security.InvalidParameterException; + +/** + * A class implementing a container for data associated with a navigation message event. + * Events are delivered to registered instances of {@link Listener}. + * + * @hide + */ +@SystemApi +public class GpsNavigationMessageEvent implements Parcelable { + + /** + * The system does not support tracking of GPS Navigation Messages. This status will not change + * in the future. + */ + public static int STATUS_NOT_SUPPORTED = 0; + + /** + * GPS Navigation Messages are successfully being tracked, it will receive updates once they are + * available. + */ + public static int STATUS_READY = 1; + + /** + * GPS provider or Location is disabled, updated will not be received until they are enabled. + */ + public static int STATUS_GPS_LOCATION_DISABLED = 2; + + private final GpsNavigationMessage mNavigationMessage; + + /** + * Used for receiving GPS satellite Navigation Messages from the GPS engine. + * You can implement this interface and call + * {@link LocationManager#addGpsNavigationMessageListener}. + * + * @hide + */ + @SystemApi + public interface Listener { + + /** + * Returns the latest collected GPS Navigation Message. + */ + void onGpsNavigationMessageReceived(GpsNavigationMessageEvent event); + + /** + * Returns the latest status of the GPS Navigation Messages sub-system. + */ + void onStatusChanged(int status); + } + + public GpsNavigationMessageEvent(GpsNavigationMessage message) { + if (message == null) { + throw new InvalidParameterException("Parameter 'message' must not be null."); + } + mNavigationMessage = message; + } + + @NonNull + public GpsNavigationMessage getNavigationMessage() { + return mNavigationMessage; + } + + public static final Creator<GpsNavigationMessageEvent> CREATOR = + new Creator<GpsNavigationMessageEvent>() { + @Override + public GpsNavigationMessageEvent createFromParcel(Parcel in) { + ClassLoader classLoader = getClass().getClassLoader(); + GpsNavigationMessage navigationMessage = in.readParcelable(classLoader); + return new GpsNavigationMessageEvent(navigationMessage); + } + + @Override + public GpsNavigationMessageEvent[] newArray(int size) { + return new GpsNavigationMessageEvent[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeParcelable(mNavigationMessage, flags); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("[ GpsNavigationMessageEvent:\n\n"); + builder.append(mNavigationMessage.toString()); + builder.append("\n]"); + return builder.toString(); + } +} diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 965dbec907ec..30cf101397db 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -1817,6 +1817,18 @@ public class LocationManager { } /** + * No-op method to keep backward-compatibility. + * Don't use it. Use {@link #registerGnssMeasurementCallback} instead. + * @hide + * @deprecated + */ + @Deprecated + @SystemApi + public boolean addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) { + return false; + } + + /** * Registers a GPS Measurement callback. * * @param callback a {@link GnssMeasurementsEvent.Callback} object to register. @@ -1841,6 +1853,17 @@ public class LocationManager { } /** + * No-op method to keep backward-compatibility. + * Don't use it. Use {@link #unregisterGnssMeasurementCallback} instead. + * @hide + * @deprecated + */ + @Deprecated + @SystemApi + public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) { + } + + /** * Unregisters a GPS Measurement callback. * * @param callback a {@link GnssMeasurementsEvent.Callback} object to remove. @@ -1850,6 +1873,18 @@ public class LocationManager { } /** + * No-op method to keep backward-compatibility. + * Don't use it. Use {@link #registerGnssNavigationMessageCallback} instead. + * @hide + * @deprecated + */ + @Deprecated + @SystemApi + public boolean addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) { + return false; + } + + /** * Registers a GPS Navigation Message callback. * * @param callback a {@link GnssNavigationMessageEvent.Callback} object to register. @@ -1883,7 +1918,18 @@ public class LocationManager { mGnssNavigationMessageCallbackTransport.remove(callback); } - /** + /** + * No-op method to keep backward-compatibility. + * Don't use it. Use {@link #unregisterGnssNavigationMessageCallback} instead. + * @hide + * @deprecated + */ + @Deprecated + @SystemApi + public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) { + } + + /** * Retrieves information about the current status of the GPS engine. * This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged} * callback to ensure that the data is copied atomically. |