diff options
author | destradaa <destradaa@google.com> | 2014-06-23 18:19:03 -0700 |
---|---|---|
committer | destradaa <destradaa@google.com> | 2014-07-11 12:20:39 -0700 |
commit | ea8a8a6076f04360de2d25b3e5853cde8026cd5f (patch) | |
tree | 7c416b43028165443b11a3e433d9044b54b9fe81 /location | |
parent | 34257d8544190979a0c1dfe63350fc50136e4dd0 (diff) | |
download | frameworks_base-ea8a8a6076f04360de2d25b3e5853cde8026cd5f.zip frameworks_base-ea8a8a6076f04360de2d25b3e5853cde8026cd5f.tar.gz frameworks_base-ea8a8a6076f04360de2d25b3e5853cde8026cd5f.tar.bz2 |
Update location framework to accept raw data from GPS HAL.
Change-Id: Ib4feca004b53fa89dcece4299974ab08913455a0
Diffstat (limited to 'location')
8 files changed, 1923 insertions, 7 deletions
diff --git a/location/java/android/location/GpsClock.java b/location/java/android/location/GpsClock.java new file mode 100644 index 0000000..f327c4e --- /dev/null +++ b/location/java/android/location/GpsClock.java @@ -0,0 +1,382 @@ +/* + * 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; + +/** + * A class containing a GPS clock timestamp. + * It represents a measurement of the GPS receiver's clock. + * + * @hide + */ +public class GpsClock implements Parcelable { + // mandatory parameters + private long mTimeInNs; + + // optional parameters + private boolean mHasLeapSecond; + private short mLeapSecond; + private boolean mHasTimeUncertaintyInNs; + private double mTimeUncertaintyInNs; + private boolean mHasBiasInNs; + private double mBiasInNs; + private boolean mHasBiasUncertaintyInNs; + private double mBiasUncertaintyInNs; + private boolean mHasDriftInNsPerSec; + private double mDriftInNsPerSec; + private boolean mHasDriftUncertaintyInNsPerSec; + private double mDriftUncertaintyInNsPerSec; + + GpsClock() { + reset(); + } + + /** + * Sets all contents to the values stored in the provided object. + */ + public void set(GpsClock clock) { + mTimeInNs = clock.mTimeInNs; + + mHasLeapSecond = clock.mHasLeapSecond; + mLeapSecond = clock.mLeapSecond; + mHasTimeUncertaintyInNs = clock.mHasTimeUncertaintyInNs; + mTimeUncertaintyInNs = clock.mTimeUncertaintyInNs; + mHasBiasInNs = clock.mHasBiasInNs; + mBiasInNs = clock.mBiasInNs; + mHasBiasUncertaintyInNs = clock.mHasBiasUncertaintyInNs; + mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs; + mHasDriftInNsPerSec = clock.mHasDriftInNsPerSec; + mDriftInNsPerSec = clock.mDriftInNsPerSec; + mHasDriftUncertaintyInNsPerSec = clock.mHasDriftUncertaintyInNsPerSec; + mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec; + } + + /** + * Resets all the contents to its original state. + */ + public void reset() { + mTimeInNs = Long.MIN_VALUE; + + resetLeapSecond(); + resetTimeUncertaintyInNs(); + resetBiasInNs(); + resetBiasUncertaintyInNs(); + resetDriftInNsPerSec(); + resetDriftUncertaintyInNsPerSec(); + } + + /** + * Returns true if {@link #getLeapSecond()} is available, false otherwise. + */ + public boolean hasLeapSecond() { + return mHasLeapSecond; + } + + /** + * Gets the leap second associated with the clock's time. + * + * 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) { + mHasLeapSecond = true; + mLeapSecond = leapSecond; + } + + /** + * Resets the leap second associated with the clock's time. + */ + public void resetLeapSecond() { + mHasLeapSecond = false; + mLeapSecond = Short.MIN_VALUE; + } + + /** + * Gets the GPS clock Time in nanoseconds; it represents the uncorrected receiver's GPS time + * since 0000Z, January 6, 1980; this is, including {@link #getBiasInNs()}. + * The reported time includes {@link #getTimeUncertaintyInNs()}. + */ + public long getTimeInNs() { + return mTimeInNs; + } + + /** + * Sets the GPS clock Time in nanoseconds. + */ + public void setTimeInNs(long timeInNs) { + mTimeInNs = timeInNs; + } + + /** + * Returns true if {@link #getTimeUncertaintyInNs()} is available, false otherwise. + */ + public boolean hasTimeUncertaintyInNs() { + return mHasTimeUncertaintyInNs; + } + + /** + * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds. + * + * 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) { + mHasTimeUncertaintyInNs = true; + mTimeUncertaintyInNs = timeUncertaintyInNs; + } + + /** + * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds. + */ + public void resetTimeUncertaintyInNs() { + mHasTimeUncertaintyInNs = false; + mTimeUncertaintyInNs = Double.NaN; + } + + /** + * Returns true if {@link #getBiasInNs()} is available, false otherwise. + */ + public boolean hasBiasInNs() { + return mHasBiasInNs; + } + + /** + * Gets the clock's Bias in nanoseconds. + * The sign of the value (if available), is defined by the following equation: + * true time = time - bias. + * The reported bias includes {@link #getBiasUncertaintyInNs()}. + * + * The value is only available if {@link #hasBiasInNs()} is true. + */ + public Double getBiasInNs() { + return mBiasInNs; + } + + /** + * Sets the clock's Bias in nanoseconds. + */ + public void setBiasInNs(double biasInNs) { + mHasBiasInNs = true; + mBiasInNs = biasInNs; + } + + /** + * Resets the clock's Bias in nanoseconds. + */ + public void resetBiasInNs() { + mHasBiasInNs = false; + mBiasInNs = Double.NaN; + } + + /** + * Returns true if {@link #getBiasUncertaintyInNs()} is available, false otherwise. + */ + public boolean hasBiasUncertaintyInNs() { + return mHasBiasUncertaintyInNs; + } + + /** + * 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) { + mHasBiasUncertaintyInNs = true; + mBiasUncertaintyInNs = biasUncertaintyInNs; + } + + /** + * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds. + */ + public void resetBiasUncertaintyInNs() { + mHasBiasUncertaintyInNs = false; + mBiasUncertaintyInNs = Double.NaN; + } + + /** + * Returns true if {@link #getDriftInNsPerSec()} is available, false otherwise. + */ + public boolean hasDriftInNsPerSec() { + return mHasDriftInNsPerSec; + } + + /** + * 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) { + mHasDriftInNsPerSec = true; + mDriftInNsPerSec = driftInNsPerSec; + } + + /** + * Resets the clock's Drift in nanoseconds per second. + */ + public void resetDriftInNsPerSec() { + mHasDriftInNsPerSec = false; + mDriftInNsPerSec = Double.NaN; + } + + /** + * Returns true if {@link #getDriftUncertaintyInNsPerSec()} is available, false otherwise. + */ + public boolean hasDriftUncertaintyInNsPerSec() { + return mHasDriftUncertaintyInNsPerSec; + } + + /** + * 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) { + mHasDriftUncertaintyInNsPerSec = true; + mDriftUncertaintyInNsPerSec = driftUncertaintyInNsPerSec; + } + + /** + * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second. + */ + public void resetDriftUncertaintyInNsPerSec() { + mHasDriftUncertaintyInNsPerSec = false; + mDriftUncertaintyInNsPerSec = Double.NaN; + } + + public static final Creator<GpsClock> CREATOR = new Creator<GpsClock>() { + @Override + public GpsClock createFromParcel(Parcel parcel) { + GpsClock gpsClock = new GpsClock(); + gpsClock.mTimeInNs = parcel.readLong(); + + gpsClock.mHasLeapSecond = parcel.readInt() != 0; + gpsClock.mLeapSecond = (short) parcel.readInt(); + gpsClock.mHasTimeUncertaintyInNs = parcel.readInt() != 0; + gpsClock.mTimeUncertaintyInNs = parcel.readDouble(); + gpsClock.mHasBiasInNs = parcel.readInt() != 0; + gpsClock.mBiasInNs = parcel.readDouble(); + gpsClock.mHasBiasUncertaintyInNs = parcel.readInt() != 0; + gpsClock.mBiasUncertaintyInNs = parcel.readDouble(); + gpsClock.mHasDriftInNsPerSec = parcel.readInt() != 0; + gpsClock.mDriftInNsPerSec = parcel.readDouble(); + gpsClock.mHasDriftUncertaintyInNsPerSec = parcel.readInt() != 0; + gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble(); + + return gpsClock; + } + + @Override + public GpsClock[] newArray(int size) { + return new GpsClock[size]; + } + }; + + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeLong(mTimeInNs); + + parcel.writeInt(mHasLeapSecond ? 1 : 0); + parcel.writeInt(mLeapSecond); + parcel.writeInt(mHasTimeUncertaintyInNs ? 1 : 0); + parcel.writeDouble(mTimeUncertaintyInNs); + parcel.writeInt(mHasBiasInNs ? 1 : 0); + parcel.writeDouble(mBiasInNs); + parcel.writeInt(mHasBiasUncertaintyInNs ? 1 : 0); + parcel.writeDouble(mBiasUncertaintyInNs); + parcel.writeInt(mHasDriftInNsPerSec ? 1 : 0); + parcel.writeDouble(mDriftInNsPerSec); + parcel.writeInt(mHasDriftUncertaintyInNsPerSec ? 1 : 0); + parcel.writeDouble(mDriftUncertaintyInNsPerSec); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + final String format = " %-15s = %-25s %-26s = %s\n"; + StringBuilder builder = new StringBuilder("GpsClock:\n"); + + builder.append(String.format( + format, + "LeapSecond", + mHasLeapSecond ? mLeapSecond : null, + "", + "")); + + builder.append(String.format( + format, + "TimeInNs", + mTimeInNs, + "TimeUncertaintyInNs", + mHasTimeUncertaintyInNs ? mTimeUncertaintyInNs : null)); + + builder.append(String.format( + format, + "BiasInNs", + mHasBiasInNs ? mBiasInNs : null, + "BiasUncertaintyInNs", + mHasBiasUncertaintyInNs ? mBiasUncertaintyInNs : null)); + + builder.append(String.format( + format, + "DriftInNsPerSec", + mHasDriftInNsPerSec ? mDriftInNsPerSec : null, + "DriftUncertaintyInNsPerSec", + mHasDriftUncertaintyInNsPerSec ? mDriftUncertaintyInNsPerSec : null)); + + return builder.toString(); + } +} diff --git a/location/java/android/location/GpsMeasurement.java b/location/java/android/location/GpsMeasurement.java new file mode 100644 index 0000000..e5a8c8c --- /dev/null +++ b/location/java/android/location/GpsMeasurement.java @@ -0,0 +1,1222 @@ +/* + * 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"; + + // mandatory parameters + private byte mPrn; + private long mLocalTimeInNs; + private long mReceivedGpsTowInNs; + private double mCn0InDbHz; + private double mPseudorangeRateInMetersPerSec; + private double mPseudorangeRateUncertaintyInMetersPerSec; + private double mAccumulatedDeltaRangeInMeters; + private double mAccumulatedDeltaRangeUncertaintyInMeters; + + // optional parameters + private boolean mHasPseudorangeInMeters; + private double mPseudorangeInMeters; + private boolean mHasPseudorangeUncertaintyInMeters; + private double mPseudorangeUncertaintyInMeters; + private boolean mHasCodePhaseInChips; + private double mCodePhaseInChips; + private boolean mHasCodePhaseUncertaintyInChips; + private double mCodePhaseUncertaintyInChips; + private boolean mHasCarrierFrequencyInHz; + private float mCarrierFrequencyInHz; + private boolean mHasCarrierCycles; + private long mCarrierCycles; + private boolean mHasCarrierPhase; + private double mCarrierPhase; + private boolean mHasCarrierPhaseUncertainty; + private double mCarrierPhaseUncertainty; + private short mLossOfLock; + private boolean mHasBitNumber; + private short mBitNumber; + private boolean mHasTimeFromLastBitInNs; + private long mTimeFromLastBitInNs; + private boolean mHasDopplerShiftInHz; + private double mDopplerShiftInHz; + private boolean mHasDopplerShiftUncertaintyInHz; + private double mDopplerShiftUncertaintyInHz; + private short mMultipathIndicator; + private boolean mHasSnrInDb; + private double mSnrInDb; + private boolean mHasElevationInDeg; + private double mElevationInDeg; + private boolean mHasElevationUncertaintyInDeg; + private double mElevationUncertaintyInDeg; + private boolean mHasAzimuthInDeg; + private double mAzimuthInDeg; + private boolean mHasAzimuthUncertaintyInDeg; + private double mAzimuthUncertaintyInDeg; + private boolean mUsedInFix; + + // The following enumerations must be in sync with the values declared in gps.h + + /** + * The indicator is not available or it is unknown. + */ + public static final short LOSS_OF_LOCK_UNKNOWN = 0; + + /** + * The measurement does not present any indication of 'loss of lock'. + */ + public static final short LOSS_OF_LOCK_OK = 1; + + /** + * 'Loss of lock' detected between the previous and current observation: cycle slip possible. + */ + public static final short LOSS_OF_LOCK_CYCLE_SLIP = 2; + + /** + * The indicator is not available or it is unknown. + */ + public static final short MULTIPATH_INDICATOR_UNKNOWN = 0; + + /** + * The measurement has been indicated to use multi-path. + */ + public static final short MULTIPATH_INDICATOR_DETECTED = 1; + + /** + * The measurement has been indicated not tu use multi-path. + */ + public static final short MULTIPATH_INDICATOR_NOT_USED = 2; + + // End enumerations in sync with gps.h + + GpsMeasurement() { + reset(); + } + + /** + * Sets all contents to the values stored in the provided object. + */ + public void set(GpsMeasurement measurement) { + mPrn = measurement.mPrn; + mLocalTimeInNs = measurement.mLocalTimeInNs; + mReceivedGpsTowInNs = measurement.mReceivedGpsTowInNs; + mCn0InDbHz = measurement.mCn0InDbHz; + mPseudorangeRateInMetersPerSec = measurement.mPseudorangeRateInMetersPerSec; + mPseudorangeRateUncertaintyInMetersPerSec = + measurement.mPseudorangeRateUncertaintyInMetersPerSec; + mAccumulatedDeltaRangeInMeters = measurement.mAccumulatedDeltaRangeInMeters; + mAccumulatedDeltaRangeUncertaintyInMeters = + measurement.mAccumulatedDeltaRangeUncertaintyInMeters; + + mHasPseudorangeInMeters = measurement.mHasPseudorangeInMeters; + mPseudorangeInMeters = measurement.mPseudorangeInMeters; + mHasPseudorangeUncertaintyInMeters = measurement.mHasPseudorangeUncertaintyInMeters; + mPseudorangeUncertaintyInMeters = measurement.mPseudorangeUncertaintyInMeters; + mHasCodePhaseInChips = measurement.mHasCodePhaseInChips; + mCodePhaseInChips = measurement.mCodePhaseInChips; + mHasCodePhaseUncertaintyInChips = measurement.mHasCodePhaseUncertaintyInChips; + mCodePhaseUncertaintyInChips = measurement.mCodePhaseUncertaintyInChips; + mHasCarrierFrequencyInHz = measurement.mHasCarrierFrequencyInHz; + mCarrierFrequencyInHz = measurement.mCarrierFrequencyInHz; + mHasCarrierCycles = measurement.mHasCarrierCycles; + mCarrierCycles = measurement.mCarrierCycles; + mHasCarrierPhase = measurement.mHasCarrierPhase; + mCarrierPhase = measurement.mCarrierPhase; + mHasCarrierPhaseUncertainty = measurement.mHasCarrierPhaseUncertainty; + mCarrierPhaseUncertainty = measurement.mCarrierPhaseUncertainty; + mLossOfLock = measurement.mLossOfLock; + mHasBitNumber = measurement.mHasBitNumber; + mBitNumber = measurement.mBitNumber; + mHasTimeFromLastBitInNs = measurement.mHasTimeFromLastBitInNs; + mTimeFromLastBitInNs = measurement.mTimeFromLastBitInNs; + mHasDopplerShiftInHz = measurement.mHasDopplerShiftInHz; + mDopplerShiftInHz = measurement.mDopplerShiftInHz; + mHasDopplerShiftUncertaintyInHz = measurement.mHasDopplerShiftUncertaintyInHz; + mDopplerShiftUncertaintyInHz = measurement.mDopplerShiftUncertaintyInHz; + mMultipathIndicator = measurement.mMultipathIndicator; + mHasSnrInDb = measurement.mHasSnrInDb; + mSnrInDb = measurement.mSnrInDb; + mHasElevationInDeg = measurement.mHasElevationInDeg; + mElevationInDeg = measurement.mElevationInDeg; + mHasElevationUncertaintyInDeg = measurement.mHasElevationUncertaintyInDeg; + mElevationUncertaintyInDeg = measurement.mElevationUncertaintyInDeg; + mHasAzimuthInDeg = measurement.mHasAzimuthInDeg; + mAzimuthInDeg = measurement.mAzimuthInDeg; + mHasAzimuthUncertaintyInDeg = measurement.mHasAzimuthUncertaintyInDeg; + mAzimuthUncertaintyInDeg = measurement.mAzimuthUncertaintyInDeg; + mUsedInFix = measurement.mUsedInFix; + } + + /** + * Resets all the contents to its original state. + */ + public void reset() { + mPrn = Byte.MIN_VALUE; + mLocalTimeInNs = Long.MIN_VALUE; + mReceivedGpsTowInNs = Long.MIN_VALUE; + mCn0InDbHz = Double.MIN_VALUE; + mPseudorangeRateInMetersPerSec = Double.MIN_VALUE; + mPseudorangeRateUncertaintyInMetersPerSec = Double.MIN_VALUE; + mAccumulatedDeltaRangeInMeters = Double.MIN_VALUE; + mAccumulatedDeltaRangeUncertaintyInMeters = Double.MIN_VALUE; + + resetPseudorangeInMeters(); + resetPseudorangeUncertaintyInMeters(); + resetCodePhaseInChips(); + resetCodePhaseUncertaintyInChips(); + resetCarrierFrequencyInHz(); + resetCarrierCycles(); + resetCarrierPhase(); + resetCarrierPhaseUncertainty(); + setLossOfLock(LOSS_OF_LOCK_UNKNOWN); + resetBitNumber(); + resetTimeFromLastBitInNs(); + resetDopplerShiftInHz(); + resetDopplerShiftUncertaintyInHz(); + setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN); + resetSnrInDb(); + resetElevationInDeg(); + resetElevationUncertaintyInDeg(); + resetAzimuthInDeg(); + resetAzimuthUncertaintyInDeg(); + setUsedInFix(false); + } + + /** + * 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 local (hardware) time at which the measurement was taken in nanoseconds. + */ + public long getLocalTimeInNs() { + return mLocalTimeInNs; + } + + /** + * Sets the measurement's local (hardware) time in nanoseconds. + */ + public void setLocalTimeInNs(long value) { + mLocalTimeInNs = value; + } + + /** + * Gets the received GPS Time-of-Week in nanoseconds. + * The value is relative to the beginning of the current GPS week. + */ + public long getReceivedGpsTowInNs() { + return mReceivedGpsTowInNs; + } + + /** + * Sets the received GPS time-of-week in nanoseconds. + */ + public void setReceivedGpsTowInNs(long value) { + mReceivedGpsTowInNs = 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 the accumulated delta range since the last channel reset, in meters. + * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyInMeters()}. + */ + 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. + */ + public void setAccumulatedDeltaRangeUncertaintyInMeters(double value) { + mAccumulatedDeltaRangeUncertaintyInMeters = value; + } + + /** + * Returns true if {@link #getPseudorangeInMeters()} is available, false otherwise. + */ + public boolean hasPseudorangeInMeters() { + return mHasPseudorangeInMeters; + } + + /** + * 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) { + mHasPseudorangeInMeters = true; + mPseudorangeInMeters = value; + } + + /** + * Resets the Pseudo-range in meters. + */ + public void resetPseudorangeInMeters() { + mHasPseudorangeInMeters = false; + mPseudorangeInMeters = Double.NaN; + } + + /** + * Returns true if {@link #getPseudorangeUncertaintyInMeters()} is available, false otherwise. + */ + public boolean hasPseudorangeUncertaintyInMeters() { + return mHasPseudorangeUncertaintyInMeters; + } + + /** + * 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) { + mHasPseudorangeUncertaintyInMeters = true; + mPseudorangeUncertaintyInMeters = value; + } + + /** + * Resets the pseudo-range's uncertainty (1-Sigma) in meters. + */ + public void resetPseudorangeUncertaintyInMeters() { + mHasPseudorangeUncertaintyInMeters = false; + mPseudorangeUncertaintyInMeters = Double.NaN; + } + + /** + * Returns true if {@link #getCodePhaseInChips()} is available, false otherwise. + */ + public boolean hasCodePhaseInChips() { + return mHasCodePhaseInChips; + } + + /** + * 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) { + mHasCodePhaseInChips = true; + mCodePhaseInChips = value; + } + + /** + * Resets the Code-phase in chips. + */ + public void resetCodePhaseInChips() { + mHasCodePhaseInChips = false; + mCodePhaseInChips = Double.NaN; + } + + /** + * Returns true if {@link #getCodePhaseUncertaintyInChips()} is available, false otherwise. + */ + public boolean hasCodePhaseUncertaintyInChips() { + return mHasCodePhaseUncertaintyInChips; + } + + /** + * 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) { + mHasCodePhaseUncertaintyInChips = true; + mCodePhaseUncertaintyInChips = value; + } + + /** + * Resets the Code-phase's uncertainty (1-Sigma) in fractions of chips. + */ + public void resetCodePhaseUncertaintyInChips() { + mHasCodePhaseUncertaintyInChips = false; + mCodePhaseUncertaintyInChips = Double.NaN; + } + + /** + * Returns true if {@link #getCarrierFrequencyInHz()} is available, false otherwise. + */ + public boolean hasCarrierFrequencyInHz() { + return mHasCarrierFrequencyInHz; + } + + /** + * 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) { + mHasCarrierFrequencyInHz = true; + mCarrierFrequencyInHz = carrierFrequencyInHz; + } + + /** + * Resets the Carrier frequency (L1 or L2) in Hz. + */ + public void resetCarrierFrequencyInHz() { + mHasCarrierFrequencyInHz = false; + mCarrierFrequencyInHz = Float.NaN; + } + + /** + * Returns true if {@link #getCarrierCycles()} is available, false otherwise. + */ + public boolean hasCarrierCycles() { + return mHasCarrierCycles; + } + + /** + * 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) { + mHasCarrierCycles = true; + mCarrierCycles = value; + } + + /** + * Resets the number of full carrier cycles between the satellite and the receiver. + */ + public void resetCarrierCycles() { + mHasCarrierCycles = false; + mCarrierCycles = Long.MIN_VALUE; + } + + /** + * Returns true if {@link #getCarrierPhase()} is available, false otherwise. + */ + public boolean hasCarrierPhase() { + return mHasCarrierPhase; + } + + /** + * 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) { + mHasCarrierPhase = true; + mCarrierPhase = value; + } + + /** + * Resets the RF phase detected by the receiver. + */ + public void resetCarrierPhase() { + mHasCarrierPhase = false; + mCarrierPhase = Double.NaN; + } + + /** + * Returns true if {@link #getCarrierPhaseUncertainty()} is available, false otherwise. + */ + public boolean hasCarrierPhaseUncertainty() { + return mHasCarrierPhaseUncertainty; + } + + /** + * 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) { + mHasCarrierPhaseUncertainty = true; + mCarrierPhaseUncertainty = value; + } + + /** + * Resets the Carrier-phase's uncertainty (1-Sigma) in cycles. + */ + public void resetCarrierPhaseUncertainty() { + mHasCarrierPhaseUncertainty = false; + mCarrierPhaseUncertainty = Double.NaN; + } + + /** + * Gets a value indicating the 'loss of lock' state of the event. + */ + public short getLossOfLock() { + return mLossOfLock; + } + + /** + * Sets the 'loss of lock' status. + */ + public void setLossOfLock(short 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 mHasBitNumber; + } + + /** + * Gets the number of GPS bits transmitted since Sat-Sun midnight (GPS week). + * + * The value is only available if {@link #hasBitNumber()} is true. + */ + public short getBitNumber() { + return mBitNumber; + } + + /** + * Sets the bit number within the broadcast frame. + */ + public void setBitNumber(short bitNumber) { + mHasBitNumber = true; + mBitNumber = bitNumber; + } + + /** + * Resets the bit number within the broadcast frame. + */ + public void resetBitNumber() { + mHasBitNumber = false; + mBitNumber = Short.MIN_VALUE; + } + + /** + * Returns true if {@link #getTimeFromLastBitInNs()} is available, false otherwise. + */ + public boolean hasTimeFromLastBitInNs() { + return mHasTimeFromLastBitInNs; + } + + /** + * Gets the elapsed time since the last received bit in nanoseconds. + * Range: [0, 20000000]. + * + * The value is only available if {@link #hasTimeFromLastBitInNs()} is true. + */ + public long getTimeFromLastBitInNs() { + return mTimeFromLastBitInNs; + } + + /** + * Sets the elapsed time since the last received bit in nanoseconds. + */ + public void setTimeFromLastBitInNs(long value) { + mHasTimeFromLastBitInNs = true; + mTimeFromLastBitInNs = value; + } + + /** + * Resets the elapsed time since the last received bit in nanoseconds. + */ + public void resetTimeFromLastBitInNs() { + mHasTimeFromLastBitInNs = false; + mTimeFromLastBitInNs = Long.MIN_VALUE; + } + + /** + * Returns true if {@link #getDopplerShiftInHz()} is available, false otherwise. + */ + public boolean hasDopplerShiftInHz() { + return mHasDopplerShiftInHz; + } + + /** + * 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) { + mHasDopplerShiftInHz = true; + mDopplerShiftInHz = value; + } + + /** + * Resets the Doppler shift in Hz. + */ + public void resetDopplerShiftInHz() { + mHasDopplerShiftInHz = false; + mDopplerShiftInHz = Double.NaN; + } + + /** + * Returns true if {@link #getDopplerShiftUncertaintyInHz()} is available, false otherwise. + */ + public boolean hasDopplerShiftUncertaintyInHz() { + return mHasDopplerShiftUncertaintyInHz; + } + + /** + * 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) { + mHasDopplerShiftUncertaintyInHz = true; + mDopplerShiftUncertaintyInHz = value; + } + + /** + * Resets the Doppler's shift uncertainty (1-Sigma) in Hz. + */ + public void resetDopplerShiftUncertaintyInHz() { + mHasDopplerShiftUncertaintyInHz = false; + mDopplerShiftUncertaintyInHz = Double.NaN; + } + + /** + * Gets a value indicating the 'multipath' state of the event. + */ + public short getMultipathIndicator() { + return mMultipathIndicator; + } + + /** + * Sets the 'multi-path' indicator. + */ + public void setMultipathIndicator(short 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 "NotDetected"; + default: + return "Invalid"; + } + } + + /** + * Returns true if {@link #getSnrInDb()} is available, false otherwise. + */ + public boolean hasSnrInDb() { + return mHasSnrInDb; + } + + /** + * 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) { + mHasSnrInDb = true; + mSnrInDb = snrInDb; + } + + /** + * Resets the Signal-to-noise ratio (SNR) in dB. + */ + public void resetSnrInDb() { + mHasSnrInDb = false; + mSnrInDb = Double.NaN; + } + + /** + * Returns true if {@link #getElevationInDeg()} is available, false otherwise. + */ + public boolean hasElevationInDeg() { + return mHasElevationInDeg; + } + + /** + * 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) { + mHasElevationInDeg = true; + mElevationInDeg = elevationInDeg; + } + + /** + * Resets the Elevation in degrees. + */ + public void resetElevationInDeg() { + mHasElevationInDeg = false; + mElevationInDeg = Double.NaN; + } + + /** + * Returns true if {@link #getElevationUncertaintyInDeg()} is available, false otherwise. + */ + public boolean hasElevationUncertaintyInDeg() { + return mHasElevationUncertaintyInDeg; + } + + /** + * 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) { + mHasElevationUncertaintyInDeg = true; + mElevationUncertaintyInDeg = value; + } + + /** + * Resets the elevation's uncertainty (1-Sigma) in degrees. + */ + public void resetElevationUncertaintyInDeg() { + mHasElevationUncertaintyInDeg = false; + mElevationUncertaintyInDeg = Double.NaN; + } + + /** + * Returns true if {@link #getAzimuthInDeg()} is available, false otherwise. + */ + public boolean hasAzimuthInDeg() { + return mHasAzimuthInDeg; + } + + /** + * 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) { + mHasAzimuthInDeg = true; + mAzimuthInDeg = value; + } + + /** + * Resets the Azimuth in degrees. + */ + public void resetAzimuthInDeg() { + mHasAzimuthInDeg = false; + mAzimuthInDeg = Double.NaN; + } + + /** + * Returns true if {@link #getAzimuthUncertaintyInDeg()} is available, false otherwise. + */ + public boolean hasAzimuthUncertaintyInDeg() { + return mHasAzimuthUncertaintyInDeg; + } + + /** + * 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) { + mHasAzimuthUncertaintyInDeg = true; + mAzimuthUncertaintyInDeg = value; + } + + /** + * Resets the Azimuth's uncertainty (1-Sigma) in degrees. + */ + public void resetAzimuthUncertaintyInDeg() { + mHasAzimuthUncertaintyInDeg = false; + 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.mPrn = parcel.readByte(); + gpsMeasurement.mLocalTimeInNs = parcel.readLong(); + gpsMeasurement.mReceivedGpsTowInNs = parcel.readLong(); + gpsMeasurement.mCn0InDbHz = parcel.readDouble(); + gpsMeasurement.mPseudorangeRateInMetersPerSec = parcel.readDouble(); + gpsMeasurement.mPseudorangeRateUncertaintyInMetersPerSec = parcel.readDouble(); + gpsMeasurement.mAccumulatedDeltaRangeInMeters = parcel.readDouble(); + gpsMeasurement.mAccumulatedDeltaRangeUncertaintyInMeters = parcel.readDouble(); + + gpsMeasurement.mHasPseudorangeInMeters = parcel.readInt() != 0; + gpsMeasurement.mPseudorangeInMeters = parcel.readDouble(); + gpsMeasurement.mHasPseudorangeUncertaintyInMeters = parcel.readInt() != 0; + gpsMeasurement.mPseudorangeUncertaintyInMeters = parcel.readDouble(); + gpsMeasurement.mHasCodePhaseInChips = parcel.readInt() != 0; + gpsMeasurement.mCodePhaseInChips = parcel.readDouble(); + gpsMeasurement.mHasCodePhaseUncertaintyInChips = parcel.readInt() != 0; + gpsMeasurement.mCodePhaseUncertaintyInChips = parcel.readDouble(); + gpsMeasurement.mHasCarrierFrequencyInHz = parcel.readInt() != 0; + gpsMeasurement.mCarrierFrequencyInHz = parcel.readFloat(); + gpsMeasurement.mHasCarrierCycles = parcel.readInt() != 0; + gpsMeasurement.mCarrierCycles = parcel.readLong(); + gpsMeasurement.mHasCarrierPhase = parcel.readInt() != 0; + gpsMeasurement.mCarrierPhase = parcel.readDouble(); + gpsMeasurement.mHasCarrierPhaseUncertainty = parcel.readInt() != 0; + gpsMeasurement.mCarrierPhaseUncertainty = parcel.readDouble(); + gpsMeasurement.mLossOfLock = (short) parcel.readInt(); + gpsMeasurement.mHasBitNumber = parcel.readInt() != 0; + gpsMeasurement.mBitNumber = (short) parcel.readInt(); + gpsMeasurement.mHasTimeFromLastBitInNs = parcel.readInt() != 0; + gpsMeasurement.mTimeFromLastBitInNs = parcel.readLong(); + gpsMeasurement.mHasDopplerShiftInHz = parcel.readInt() != 0; + gpsMeasurement.mDopplerShiftInHz = parcel.readDouble(); + gpsMeasurement.mHasDopplerShiftUncertaintyInHz = parcel.readInt() != 0; + gpsMeasurement.mDopplerShiftUncertaintyInHz = parcel.readDouble(); + gpsMeasurement.mMultipathIndicator = (short) parcel.readInt(); + gpsMeasurement.mHasSnrInDb = parcel.readInt() != 0; + gpsMeasurement.mSnrInDb = parcel.readDouble(); + gpsMeasurement.mHasElevationInDeg = parcel.readInt() != 0; + gpsMeasurement.mElevationInDeg = parcel.readDouble(); + gpsMeasurement.mHasElevationUncertaintyInDeg = parcel.readInt() != 0; + gpsMeasurement.mElevationUncertaintyInDeg = parcel.readDouble(); + gpsMeasurement.mHasAzimuthInDeg = parcel.readInt() != 0; + gpsMeasurement.mAzimuthInDeg = parcel.readDouble(); + gpsMeasurement.mHasAzimuthUncertaintyInDeg = parcel.readInt() != 0; + 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.writeByte(mPrn); + parcel.writeLong(mLocalTimeInNs); + parcel.writeLong(mReceivedGpsTowInNs); + parcel.writeDouble(mCn0InDbHz); + parcel.writeDouble(mPseudorangeRateInMetersPerSec); + parcel.writeDouble(mPseudorangeRateUncertaintyInMetersPerSec); + parcel.writeDouble(mAccumulatedDeltaRangeInMeters); + parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyInMeters); + + parcel.writeInt(mHasPseudorangeInMeters ? 1 : 0); + parcel.writeDouble(mPseudorangeInMeters); + parcel.writeInt(mHasPseudorangeUncertaintyInMeters ? 1 : 0); + parcel.writeDouble(mPseudorangeUncertaintyInMeters); + parcel.writeInt(mHasCodePhaseInChips ? 1 : 0); + parcel.writeDouble(mCodePhaseInChips); + parcel.writeInt(mHasCodePhaseUncertaintyInChips ? 1 : 0); + parcel.writeDouble(mCodePhaseUncertaintyInChips); + parcel.writeInt(mHasCarrierFrequencyInHz ? 1 : 0); + parcel.writeFloat(mCarrierFrequencyInHz); + parcel.writeInt(mHasCarrierCycles ? 1 : 0); + parcel.writeLong(mCarrierCycles); + parcel.writeInt(mHasCarrierPhase ? 1 : 0); + parcel.writeDouble(mCarrierPhase); + parcel.writeInt(mHasCarrierPhaseUncertainty ? 1 : 0); + parcel.writeDouble(mCarrierPhaseUncertainty); + parcel.writeInt(mLossOfLock); + parcel.writeInt(mHasBitNumber ? 1 : 0); + parcel.writeInt(mBitNumber); + parcel.writeInt(mHasTimeFromLastBitInNs ? 1 : 0); + parcel.writeLong(mTimeFromLastBitInNs); + parcel.writeInt(mHasDopplerShiftInHz ? 1 : 0); + parcel.writeDouble(mDopplerShiftInHz); + parcel.writeInt(mHasDopplerShiftUncertaintyInHz ? 1 : 0); + parcel.writeDouble(mDopplerShiftUncertaintyInHz); + parcel.writeInt(mMultipathIndicator); + parcel.writeInt(mHasSnrInDb ? 1 : 0); + parcel.writeDouble(mSnrInDb); + parcel.writeInt(mHasElevationInDeg ? 1 : 0); + parcel.writeDouble(mElevationInDeg); + parcel.writeInt(mHasElevationUncertaintyInDeg ? 1 : 0); + parcel.writeDouble(mElevationUncertaintyInDeg); + parcel.writeInt(mHasAzimuthInDeg ? 1 : 0); + parcel.writeDouble(mAzimuthInDeg); + parcel.writeInt(mHasAzimuthUncertaintyInDeg ? 1 : 0); + 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, "LocalTimeInNs", mLocalTimeInNs)); + + builder.append(String.format(format, "ReceivedGpsTowInNs", mReceivedGpsTowInNs)); + + builder.append(String.format(format, "Cn0InDbHz", mCn0InDbHz)); + + builder.append(String.format( + formatWithUncertainty, + "PseudorangeRateInMetersPerSec", + mPseudorangeRateInMetersPerSec, + "PseudorangeRateUncertaintyInMetersPerSec", + mPseudorangeRateUncertaintyInMetersPerSec)); + + builder.append(String.format( + formatWithUncertainty, + "AccumulatedDeltaRangeInMeters", + mAccumulatedDeltaRangeInMeters, + "AccumulatedDeltaRangeUncertaintyInMeters", + mAccumulatedDeltaRangeUncertaintyInMeters)); + + + builder.append(String.format( + formatWithUncertainty, + "PseudorangeInMeters", + mHasPseudorangeInMeters ? mPseudorangeInMeters : null, + "PseudorangeUncertaintyInMeters", + mHasPseudorangeUncertaintyInMeters ? mPseudorangeUncertaintyInMeters : null)); + + builder.append(String.format( + formatWithUncertainty, + "CodePhaseInChips", + mHasCodePhaseInChips ? mCodePhaseInChips : null, + "CodePhaseUncertaintyInChips", + mHasCodePhaseUncertaintyInChips ? mCodePhaseUncertaintyInChips : null)); + + builder.append(String.format( + format, + "CarrierFrequencyInHz", + mHasCarrierFrequencyInHz ? mCarrierFrequencyInHz : null)); + + builder.append(String.format( + format, + "CarrierCycles", + mHasCarrierCycles ? mCarrierCycles : null)); + + builder.append(String.format( + formatWithUncertainty, + "CarrierPhase", + mHasCarrierPhase ? mCarrierPhase : null, + "CarrierPhaseUncertainty", + mHasCarrierPhaseUncertainty ? mCarrierPhaseUncertainty : null)); + + builder.append(String.format(format, "LossOfLock", getLossOfLockString())); + + builder.append(String.format( + format, + "BitNumber", + mHasBitNumber ? mBitNumber : null)); + + builder.append(String.format( + format, + "TimeFromLastBitInNs", + mHasTimeFromLastBitInNs ? mTimeFromLastBitInNs : null)); + + builder.append(String.format( + formatWithUncertainty, + "DopplerShiftInHz", + mHasDopplerShiftInHz ? mDopplerShiftInHz : null, + "DopplerShiftUncertaintyInHz", + mHasDopplerShiftUncertaintyInHz ? mDopplerShiftUncertaintyInHz : null)); + + builder.append(String.format(format, "MultipathIndicator", getMultipathIndicatorString())); + + builder.append(String.format( + format, + "SnrInDb", + mHasSnrInDb ? mSnrInDb : null)); + + builder.append(String.format( + formatWithUncertainty, + "ElevationInDeg", + mHasElevationInDeg ? mElevationInDeg : null, + "ElevationUncertaintyInDeg", + mHasElevationUncertaintyInDeg ? mElevationUncertaintyInDeg : null)); + + builder.append(String.format( + formatWithUncertainty, + "AzimuthInDeg", + mHasAzimuthInDeg ? mAzimuthInDeg : null, + "AzimuthUncertaintyInDeg", + mHasAzimuthUncertaintyInDeg ? mAzimuthUncertaintyInDeg : null)); + + builder.append(String.format(format, "UsedInFix", mUsedInFix)); + + return builder.toString(); + } +} diff --git a/location/java/android/location/GpsMeasurementListenerTransport.java b/location/java/android/location/GpsMeasurementListenerTransport.java new file mode 100644 index 0000000..48a4b44 --- /dev/null +++ b/location/java/android/location/GpsMeasurementListenerTransport.java @@ -0,0 +1,114 @@ +/* + * 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 com.android.internal.util.Preconditions; + +import android.annotation.NonNull; +import android.content.Context; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; + +/** + * A handler class to manage transport listeners for {@link GpsMeasurementsEvent.Listener}, + * and post the events in a handler. + * + * @hide + */ +class GpsMeasurementListenerTransport { + private static final String TAG = "GpsMeasurementListenerTransport"; + + private final Context mContext; + private final ILocationManager mLocationManager; + + private final IGpsMeasurementsListener mListenerTransport = new ListenerTransport(); + private final HashSet<GpsMeasurementsEvent.Listener> mListeners = + new HashSet<GpsMeasurementsEvent.Listener>(); + + public GpsMeasurementListenerTransport(Context context, ILocationManager locationManager) { + mContext = context; + mLocationManager = locationManager; + } + + public boolean add(@NonNull GpsMeasurementsEvent.Listener listener) { + Preconditions.checkNotNull(listener); + + synchronized (mListeners) { + // we need to register with the service first, because we need to find out if the + // service will actually support the request before we attempt anything + if (mListeners.isEmpty()) { + boolean registeredWithServer; + try { + registeredWithServer = mLocationManager.addGpsMeasurementsListener( + mListenerTransport, + mContext.getPackageName()); + } catch (RemoteException e) { + Log.e(TAG, "Error handling first listener.", e); + return false; + } + + if (!registeredWithServer) { + Log.e(TAG, "Unable to register listener transport."); + return false; + } + } + + if (mListeners.contains(listener)) { + return true; + } + + mListeners.add(listener); + } + + return true; + } + + public void remove(@NonNull GpsMeasurementsEvent.Listener listener) { + Preconditions.checkNotNull(listener); + + synchronized (mListeners) { + boolean removed = mListeners.remove(listener); + + boolean isLastListener = removed && mListeners.isEmpty(); + if (isLastListener) { + try { + mLocationManager.removeGpsMeasurementsListener(mListenerTransport); + } catch (RemoteException e) { + Log.e(TAG, "Error handling last listener.", e); + } + } + } + } + + private class ListenerTransport extends IGpsMeasurementsListener.Stub { + @Override + public void onGpsMeasurementsReceived(final GpsMeasurementsEvent eventArgs) { + Collection<GpsMeasurementsEvent.Listener> listeners; + synchronized (mListeners) { + listeners = new ArrayList<GpsMeasurementsEvent.Listener>(mListeners); + } + + for (final GpsMeasurementsEvent.Listener listener : listeners) { + listener.onGpsMeasurementsReceived(eventArgs); + } + } + } +} diff --git a/location/java/android/location/GpsMeasurementsEvent.aidl b/location/java/android/location/GpsMeasurementsEvent.aidl new file mode 100644 index 0000000..2c46262 --- /dev/null +++ b/location/java/android/location/GpsMeasurementsEvent.aidl @@ -0,0 +1,19 @@ +/* + * 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; + +parcelable GpsMeasurementsEvent; diff --git a/location/java/android/location/GpsMeasurementsEvent.java b/location/java/android/location/GpsMeasurementsEvent.java new file mode 100644 index 0000000..e04ed81 --- /dev/null +++ b/location/java/android/location/GpsMeasurementsEvent.java @@ -0,0 +1,127 @@ +/* + * 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.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 + */ +public class GpsMeasurementsEvent implements Parcelable { + 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 + */ + public interface Listener { + void onGpsMeasurementsReceived(GpsMeasurementsEvent eventArgs); + } + + 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); + + GpsMeasurement[] measurementsArray = mReadOnlyMeasurements.toArray(new GpsMeasurement[0]); + 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/IGpsMeasurementsListener.aidl b/location/java/android/location/IGpsMeasurementsListener.aidl new file mode 100644 index 0000000..b34bb6c --- /dev/null +++ b/location/java/android/location/IGpsMeasurementsListener.aidl @@ -0,0 +1,26 @@ +/* + * 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.location.GpsMeasurementsEvent; + +/** + * {@hide} + */ +oneway interface IGpsMeasurementsListener { + void onGpsMeasurementsReceived(in GpsMeasurementsEvent event); +} diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index c353ec6..a1acaf1 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -21,7 +21,7 @@ import android.location.Address; import android.location.Criteria; import android.location.GeocoderParams; import android.location.Geofence; -import android.location.IGeocodeProvider; +import android.location.IGpsMeasurementsListener; import android.location.IGpsStatusListener; import android.location.ILocationListener; import android.location.Location; @@ -60,6 +60,9 @@ interface ILocationManager boolean sendNiResponse(int notifId, int userResponse); + boolean addGpsMeasurementsListener(in IGpsMeasurementsListener listener, in String packageName); + boolean removeGpsMeasurementsListener(in IGpsMeasurementsListener listener); + // --- deprecated --- List<String> getAllProviders(); List<String> getProviders(in Criteria criteria, boolean enabledOnly); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 4502a5b..d6a8fb8 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -16,25 +16,23 @@ package android.location; +import com.android.internal.location.ProviderProperties; + import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Bundle; -import android.os.Looper; -import android.os.RemoteException; import android.os.Handler; +import android.os.Looper; import android.os.Message; +import android.os.RemoteException; import android.util.Log; - -import java.lang.SecurityException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import com.android.internal.location.ProviderProperties; - /** * This class provides access to the system location services. These * services allow applications to obtain periodic updates of the @@ -60,6 +58,7 @@ public class LocationManager { private final Context mContext; private final ILocationManager mService; + private final GpsMeasurementListenerTransport mGpsMeasurementListenerTransport; private final HashMap<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners = new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>(); private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners = @@ -310,6 +309,7 @@ public class LocationManager { public LocationManager(Context context, ILocationManager service) { mService = service; mContext = context; + mGpsMeasurementListenerTransport = new GpsMeasurementListenerTransport(mContext, mService); } private LocationProvider createProvider(String name, ProviderProperties properties) { @@ -1570,6 +1570,29 @@ public class LocationManager { } } + /** + * Adds a GPS Measurement listener. + * + * @param listener a {@link android.location.GpsMeasurementsEvent.Listener} object to register. + * @return {@code true} if the listener was successfully registered, {@code false} otherwise. + * + * @hide + */ + public boolean addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) { + return mGpsMeasurementListenerTransport.add(listener); + } + + /** + * Removes a GPS Measurement listener. + * + * @param listener a {@link GpsMeasurementsEvent.Listener} object to remove. + * + * @hide + */ + public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) { + mGpsMeasurementListenerTransport.remove(listener); + } + /** * Retrieves information about the current status of the GPS engine. * This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged} |