1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package android.location;
18
19import android.annotation.SystemApi;
20import android.os.Parcel;
21import android.os.Parcelable;
22
23/**
24 * A class representing a GPS satellite measurement, containing raw and computed information.
25 *
26 * @hide
27 */
28@SystemApi
29public class GpsMeasurement implements Parcelable {
30    private int mFlags;
31    private byte mPrn;
32    private double mTimeOffsetInNs;
33    private short mState;
34    private long mReceivedGpsTowInNs;
35    private long mReceivedGpsTowUncertaintyInNs;
36    private double mCn0InDbHz;
37    private double mPseudorangeRateInMetersPerSec;
38    private double mPseudorangeRateUncertaintyInMetersPerSec;
39    private short mAccumulatedDeltaRangeState;
40    private double mAccumulatedDeltaRangeInMeters;
41    private double mAccumulatedDeltaRangeUncertaintyInMeters;
42    private double mPseudorangeInMeters;
43    private double mPseudorangeUncertaintyInMeters;
44    private double mCodePhaseInChips;
45    private double mCodePhaseUncertaintyInChips;
46    private float mCarrierFrequencyInHz;
47    private long mCarrierCycles;
48    private double mCarrierPhase;
49    private double mCarrierPhaseUncertainty;
50    private byte mLossOfLock;
51    private int mBitNumber;
52    private short mTimeFromLastBitInMs;
53    private double mDopplerShiftInHz;
54    private double mDopplerShiftUncertaintyInHz;
55    private byte mMultipathIndicator;
56    private double mSnrInDb;
57    private double mElevationInDeg;
58    private double mElevationUncertaintyInDeg;
59    private double mAzimuthInDeg;
60    private double mAzimuthUncertaintyInDeg;
61    private boolean mUsedInFix;
62
63    // The following enumerations must be in sync with the values declared in gps.h
64
65    private static final int HAS_NO_FLAGS = 0;
66    private static final int HAS_SNR = (1<<0);
67    private static final int HAS_ELEVATION = (1<<1);
68    private static final int HAS_ELEVATION_UNCERTAINTY = (1<<2);
69    private static final int HAS_AZIMUTH = (1<<3);
70    private static final int HAS_AZIMUTH_UNCERTAINTY = (1<<4);
71    private static final int HAS_PSEUDORANGE = (1<<5);
72    private static final int HAS_PSEUDORANGE_UNCERTAINTY = (1<<6);
73    private static final int HAS_CODE_PHASE = (1<<7);
74    private static final int HAS_CODE_PHASE_UNCERTAINTY = (1<<8);
75    private static final int HAS_CARRIER_FREQUENCY = (1<<9);
76    private static final int HAS_CARRIER_CYCLES = (1<<10);
77    private static final int HAS_CARRIER_PHASE = (1<<11);
78    private static final int HAS_CARRIER_PHASE_UNCERTAINTY = (1<<12);
79    private static final int HAS_BIT_NUMBER = (1<<13);
80    private static final int HAS_TIME_FROM_LAST_BIT = (1<<14);
81    private static final int HAS_DOPPLER_SHIFT = (1<<15);
82    private static final int HAS_DOPPLER_SHIFT_UNCERTAINTY = (1<<16);
83    private static final int HAS_USED_IN_FIX = (1<<17);
84    private static final int GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18);
85
86    /**
87     * The indicator is not available or it is unknown.
88     */
89    public static final byte LOSS_OF_LOCK_UNKNOWN = 0;
90
91    /**
92     * The measurement does not present any indication of 'loss of lock'.
93     */
94    public static final byte LOSS_OF_LOCK_OK = 1;
95
96    /**
97     * 'Loss of lock' detected between the previous and current observation: cycle slip possible.
98     */
99    public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2;
100
101    /**
102     * The indicator is not available or it is unknown.
103     */
104    public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0;
105
106    /**
107     * The measurement has been indicated to use multi-path.
108     */
109    public static final byte MULTIPATH_INDICATOR_DETECTED = 1;
110
111    /**
112     * The measurement has been indicated not tu use multi-path.
113     */
114    public static final byte MULTIPATH_INDICATOR_NOT_USED = 2;
115
116    /**
117     * The state of GPS receiver the measurement is invalid or unknown.
118     */
119    public static final short STATE_UNKNOWN = 0;
120
121    /**
122     * The state of the GPS receiver is ranging code lock.
123     */
124    public static final short STATE_CODE_LOCK = (1<<0);
125
126    /**
127     * The state of the GPS receiver is in bit sync.
128     */
129    public static final short STATE_BIT_SYNC = (1<<1);
130
131    /**
132     *The state of the GPS receiver is in sub-frame sync.
133     */
134    public static final short STATE_SUBFRAME_SYNC = (1<<2);
135
136    /**
137     * The state of the GPS receiver has TOW decoded.
138     */
139    public static final short STATE_TOW_DECODED = (1<<3);
140
141    /**
142     * The state of the GPS receiver contains millisecond ambiguity.
143     */
144    public static final short STATE_MSEC_AMBIGUOUS = (1<<4);
145
146    /**
147     * All the GPS receiver state flags.
148     */
149    private static final short STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC
150            | STATE_TOW_DECODED | STATE_MSEC_AMBIGUOUS;
151
152    /**
153     * The state of the 'Accumulated Delta Range' is invalid or unknown.
154     */
155    public static final short ADR_STATE_UNKNOWN = 0;
156
157    /**
158     * The state of the 'Accumulated Delta Range' is valid.
159     */
160    public static final short ADR_STATE_VALID = (1<<0);
161
162    /**
163     * The state of the 'Accumulated Delta Range' has detected a reset.
164     */
165    public static final short ADR_STATE_RESET = (1<<1);
166
167    /**
168     * The state of the 'Accumulated Delta Range' has a cycle slip detected.
169     */
170    public static final short ADR_STATE_CYCLE_SLIP = (1<<2);
171
172    /**
173     * All the 'Accumulated Delta Range' flags.
174     */
175    private static final short ADR_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP;
176
177    // End enumerations in sync with gps.h
178
179    GpsMeasurement() {
180        initialize();
181    }
182
183    /**
184     * Sets all contents to the values stored in the provided object.
185     */
186    public void set(GpsMeasurement measurement) {
187        mFlags = measurement.mFlags;
188        mPrn = measurement.mPrn;
189        mTimeOffsetInNs = measurement.mTimeOffsetInNs;
190        mState = measurement.mState;
191        mReceivedGpsTowInNs = measurement.mReceivedGpsTowInNs;
192        mReceivedGpsTowUncertaintyInNs = measurement.mReceivedGpsTowUncertaintyInNs;
193        mCn0InDbHz = measurement.mCn0InDbHz;
194        mPseudorangeRateInMetersPerSec = measurement.mPseudorangeRateInMetersPerSec;
195        mPseudorangeRateUncertaintyInMetersPerSec =
196                measurement.mPseudorangeRateUncertaintyInMetersPerSec;
197        mAccumulatedDeltaRangeState = measurement.mAccumulatedDeltaRangeState;
198        mAccumulatedDeltaRangeInMeters = measurement.mAccumulatedDeltaRangeInMeters;
199        mAccumulatedDeltaRangeUncertaintyInMeters =
200                measurement.mAccumulatedDeltaRangeUncertaintyInMeters;
201        mPseudorangeInMeters = measurement.mPseudorangeInMeters;
202        mPseudorangeUncertaintyInMeters = measurement.mPseudorangeUncertaintyInMeters;
203        mCodePhaseInChips = measurement.mCodePhaseInChips;
204        mCodePhaseUncertaintyInChips = measurement.mCodePhaseUncertaintyInChips;
205        mCarrierFrequencyInHz = measurement.mCarrierFrequencyInHz;
206        mCarrierCycles = measurement.mCarrierCycles;
207        mCarrierPhase = measurement.mCarrierPhase;
208        mCarrierPhaseUncertainty = measurement.mCarrierPhaseUncertainty;
209        mLossOfLock = measurement.mLossOfLock;
210        mBitNumber = measurement.mBitNumber;
211        mTimeFromLastBitInMs = measurement.mTimeFromLastBitInMs;
212        mDopplerShiftInHz = measurement.mDopplerShiftInHz;
213        mDopplerShiftUncertaintyInHz = measurement.mDopplerShiftUncertaintyInHz;
214        mMultipathIndicator = measurement.mMultipathIndicator;
215        mSnrInDb = measurement.mSnrInDb;
216        mElevationInDeg = measurement.mElevationInDeg;
217        mElevationUncertaintyInDeg = measurement.mElevationUncertaintyInDeg;
218        mAzimuthInDeg = measurement.mAzimuthInDeg;
219        mAzimuthUncertaintyInDeg = measurement.mAzimuthUncertaintyInDeg;
220        mUsedInFix = measurement.mUsedInFix;
221    }
222
223    /**
224     * Resets all the contents to its original state.
225     */
226    public void reset() {
227        initialize();
228    }
229
230    /**
231     * Gets the Pseudo-random number (PRN).
232     * Range: [1, 32]
233     */
234    public byte getPrn() {
235        return mPrn;
236    }
237
238    /**
239     * Sets the Pseud-random number (PRN).
240     */
241    public void setPrn(byte value) {
242        mPrn = value;
243    }
244
245    /**
246     * Gets the time offset at which the measurement was taken in nanoseconds.
247     * The reference receiver's time is specified by {@link GpsClock#getTimeInNs()} and should be
248     * interpreted in the same way as indicated by {@link GpsClock#getType()}.
249     *
250     * The sign of this value is given by the following equation:
251     *      measurement time = time_ns + time_offset_ns
252     *
253     * The value provides an individual time-stamp for the measurement, and allows sub-nanosecond
254     * accuracy.
255     */
256    public double getTimeOffsetInNs() {
257        return mTimeOffsetInNs;
258    }
259
260    /**
261     * Sets the time offset at which the measurement was taken in nanoseconds.
262     */
263    public void setTimeOffsetInNs(double value) {
264        mTimeOffsetInNs = value;
265    }
266
267    /**
268     * Gets per-satellite sync state.
269     * It represents the current sync state for the associated satellite.
270     *
271     * This value helps interpret {@link #getReceivedGpsTowInNs()}.
272     */
273    public short getState() {
274        return mState;
275    }
276
277    /**
278     * Sets the sync state.
279     */
280    public void setState(short value) {
281        mState = value;
282    }
283
284    /**
285     * Gets a string representation of the 'sync state'.
286     * For internal and logging use only.
287     */
288    private String getStateString() {
289        if (mState == STATE_UNKNOWN) {
290            return "Unknown";
291        }
292        StringBuilder builder = new StringBuilder();
293        if ((mState & STATE_CODE_LOCK) == STATE_CODE_LOCK) {
294            builder.append("CodeLock|");
295        }
296        if ((mState & STATE_BIT_SYNC) == STATE_BIT_SYNC) {
297            builder.append("BitSync|");
298        }
299        if ((mState & STATE_SUBFRAME_SYNC) == STATE_SUBFRAME_SYNC) {
300            builder.append("SubframeSync|");
301        }
302        if ((mState & STATE_TOW_DECODED) == STATE_TOW_DECODED) {
303            builder.append("TowDecoded|");
304        }
305        if ((mState & STATE_MSEC_AMBIGUOUS) == STATE_MSEC_AMBIGUOUS) {
306            builder.append("MsecAmbiguous");
307        }
308        int remainingStates = mState & ~STATE_ALL;
309        if (remainingStates > 0) {
310            builder.append("Other(");
311            builder.append(Integer.toBinaryString(remainingStates));
312            builder.append(")|");
313        }
314        builder.deleteCharAt(builder.length() - 1);
315        return builder.toString();
316    }
317
318    /**
319     * Gets the received GPS Time-of-Week at the measurement time, in nanoseconds.
320     * The value is relative to the beginning of the current GPS week.
321     *
322     * Given {@link #getState()} of the GPS receiver, the range of this field can be:
323     *      Searching           : [ 0           ]   : {@link #STATE_UNKNOWN} is set
324     *      Ranging code lock   : [ 0    1 ms   ]   : {@link #STATE_CODE_LOCK} is set
325     *      Bit sync            : [ 0   20 ms   ]   : {@link #STATE_BIT_SYNC} is set
326     *      Subframe sync       : [ 0    6 ms   ]   : {@link #STATE_SUBFRAME_SYNC} is set
327     *      TOW decoded         : [ 0    1 week ]   : {@link #STATE_TOW_DECODED} is set
328     */
329    public long getReceivedGpsTowInNs() {
330        return mReceivedGpsTowInNs;
331    }
332
333    /**
334     * Sets the received GPS time-of-week in nanoseconds.
335     */
336    public void setReceivedGpsTowInNs(long value) {
337        mReceivedGpsTowInNs = value;
338    }
339
340    /**
341     * Gets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds.
342     */
343    public long getReceivedGpsTowUncertaintyInNs() {
344        return mReceivedGpsTowUncertaintyInNs;
345    }
346
347    /**
348     * Sets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds.
349     */
350    public void setReceivedGpsTowUncertaintyInNs(long value) {
351        mReceivedGpsTowUncertaintyInNs = value;
352    }
353
354    /**
355     * Gets the Carrier-to-noise density in dB-Hz.
356     * Range: [0, 63].
357     *
358     * The value contains the measured C/N0 for the signal at the antenna input.
359     */
360    public double getCn0InDbHz() {
361        return mCn0InDbHz;
362    }
363
364    /**
365     * Sets the carrier-to-noise density in dB-Hz.
366     */
367    public void setCn0InDbHz(double value) {
368        mCn0InDbHz = value;
369    }
370
371    /**
372     * Gets the Pseudorange rate at the timestamp in m/s.
373     * The reported value includes {@link #getPseudorangeRateUncertaintyInMetersPerSec()}.
374     *
375     * The correction of a given Pseudorange Rate value includes corrections from receiver and
376     * satellite clock frequency errors.
377     * {@link #isPseudorangeRateCorrected()} identifies the type of value reported.
378     *
379     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
380     * The sign of the 'uncorrected' Pseudorange Rate and its relation to the sign of
381     * {@link #getDopplerShiftInHz()} is given by the equation:
382     *      pseudorange rate = -k * doppler shift   (where k is a constant)
383     */
384    public double getPseudorangeRateInMetersPerSec() {
385        return mPseudorangeRateInMetersPerSec;
386    }
387
388    /**
389     * Sets the pseudorange rate at the timestamp in m/s.
390     */
391    public void setPseudorangeRateInMetersPerSec(double value) {
392        mPseudorangeRateInMetersPerSec = value;
393    }
394
395    /**
396     * See {@link #getPseudorangeRateInMetersPerSec()} for more details.
397     *
398     * @return {@code true} if {@link #getPseudorangeRateInMetersPerSec()} contains a corrected
399     *         value, {@code false} if it contains an uncorrected value.
400     */
401    public boolean isPseudorangeRateCorrected() {
402        return !isFlagSet(GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE);
403    }
404
405    /**
406     * Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
407     * The uncertainty is represented as an absolute (single sided) value.
408     */
409    public double getPseudorangeRateUncertaintyInMetersPerSec() {
410        return mPseudorangeRateUncertaintyInMetersPerSec;
411    }
412
413    /**
414     * Sets the pseudorange's rate uncertainty (1-Sigma) in m/s.
415     */
416    public void setPseudorangeRateUncertaintyInMetersPerSec(double value) {
417        mPseudorangeRateUncertaintyInMetersPerSec = value;
418    }
419
420    /**
421     * Gets 'Accumulated Delta Range' state.
422     * It indicates whether {@link #getAccumulatedDeltaRangeInMeters()} is reset or there is a
423     * cycle slip (indicating 'loss of lock').
424     */
425    public short getAccumulatedDeltaRangeState() {
426        return mAccumulatedDeltaRangeState;
427    }
428
429    /**
430     * Sets the 'Accumulated Delta Range' state.
431     */
432    public void setAccumulatedDeltaRangeState(short value) {
433        mAccumulatedDeltaRangeState = value;
434    }
435
436    /**
437     * Gets a string representation of the 'Accumulated Delta Range state'.
438     * For internal and logging use only.
439     */
440    private String getAccumulatedDeltaRangeStateString() {
441        if (mAccumulatedDeltaRangeState == ADR_STATE_UNKNOWN) {
442            return "Unknown";
443        }
444        StringBuilder builder = new StringBuilder();
445        if ((mAccumulatedDeltaRangeState & ADR_STATE_VALID) == ADR_STATE_VALID) {
446            builder.append("Valid|");
447        }
448        if ((mAccumulatedDeltaRangeState & ADR_STATE_RESET) == ADR_STATE_RESET) {
449            builder.append("Reset|");
450        }
451        if ((mAccumulatedDeltaRangeState & ADR_STATE_CYCLE_SLIP) == ADR_STATE_CYCLE_SLIP) {
452            builder.append("CycleSlip|");
453        }
454        int remainingStates = mAccumulatedDeltaRangeState & ~ADR_ALL;
455        if (remainingStates > 0) {
456            builder.append("Other(");
457            builder.append(Integer.toBinaryString(remainingStates));
458            builder.append(")|");
459        }
460        builder.deleteCharAt(builder.length() - 1);
461        return builder.toString();
462    }
463
464    /**
465     * Gets the accumulated delta range since the last channel reset, in meters.
466     * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyInMeters()}.
467     *
468     * The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
469     *
470     * A positive value indicates that the SV is moving away from the receiver.
471     * The sign of {@link #getAccumulatedDeltaRangeInMeters()} and its relation to the sign of
472     * {@link #getCarrierPhase()} is given by the equation:
473     *          accumulated delta range = -k * carrier phase    (where k is a constant)
474     */
475    public double getAccumulatedDeltaRangeInMeters() {
476        return mAccumulatedDeltaRangeInMeters;
477    }
478
479    /**
480     * Sets the accumulated delta range in meters.
481     */
482    public void setAccumulatedDeltaRangeInMeters(double value) {
483        mAccumulatedDeltaRangeInMeters = value;
484    }
485
486    /**
487     * Gets the accumulated delta range's uncertainty (1-Sigma) in meters.
488     * The uncertainty is represented as an absolute (single sided) value.
489     *
490     * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
491     */
492    public double getAccumulatedDeltaRangeUncertaintyInMeters() {
493        return mAccumulatedDeltaRangeUncertaintyInMeters;
494    }
495
496    /**
497     * Sets the accumulated delta range's uncertainty (1-sigma) in meters.
498     *
499     * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
500     */
501    public void setAccumulatedDeltaRangeUncertaintyInMeters(double value) {
502        mAccumulatedDeltaRangeUncertaintyInMeters = value;
503    }
504
505    /**
506     * Returns true if {@link #getPseudorangeInMeters()} is available, false otherwise.
507     */
508    public boolean hasPseudorangeInMeters() {
509        return isFlagSet(HAS_PSEUDORANGE);
510    }
511
512    /**
513     * Gets the best derived pseudorange by the chipset, in meters.
514     * The reported pseudorange includes {@link #getPseudorangeUncertaintyInMeters()}.
515     *
516     * The value is only available if {@link #hasPseudorangeInMeters()} is true.
517     */
518    public double getPseudorangeInMeters() {
519        return mPseudorangeInMeters;
520    }
521
522    /**
523     * Sets the Pseudo-range in meters.
524     */
525    public void setPseudorangeInMeters(double value) {
526        setFlag(HAS_PSEUDORANGE);
527        mPseudorangeInMeters = value;
528    }
529
530    /**
531     * Resets the Pseudo-range in meters.
532     */
533    public void resetPseudorangeInMeters() {
534        resetFlag(HAS_PSEUDORANGE);
535        mPseudorangeInMeters = Double.NaN;
536    }
537
538    /**
539     * Returns true if {@link #getPseudorangeUncertaintyInMeters()} is available, false otherwise.
540     */
541    public boolean hasPseudorangeUncertaintyInMeters() {
542        return isFlagSet(HAS_PSEUDORANGE_UNCERTAINTY);
543    }
544
545    /**
546     * Gets the pseudorange's uncertainty (1-Sigma) in meters.
547     * The value contains the 'pseudorange' and 'clock' uncertainty in it.
548     * The uncertainty is represented as an absolute (single sided) value.
549     *
550     * The value is only available if {@link #hasPseudorangeUncertaintyInMeters()} is true.
551     */
552    public double getPseudorangeUncertaintyInMeters() {
553        return mPseudorangeUncertaintyInMeters;
554    }
555
556    /**
557     * Sets the pseudo-range's uncertainty (1-Sigma) in meters.
558     */
559    public void setPseudorangeUncertaintyInMeters(double value) {
560        setFlag(HAS_PSEUDORANGE_UNCERTAINTY);
561        mPseudorangeUncertaintyInMeters = value;
562    }
563
564    /**
565     * Resets the pseudo-range's uncertainty (1-Sigma) in meters.
566     */
567    public void resetPseudorangeUncertaintyInMeters() {
568        resetFlag(HAS_PSEUDORANGE_UNCERTAINTY);
569        mPseudorangeUncertaintyInMeters = Double.NaN;
570    }
571
572    /**
573     * Returns true if {@link #getCodePhaseInChips()} is available, false otherwise.
574     */
575    public boolean hasCodePhaseInChips() {
576        return isFlagSet(HAS_CODE_PHASE);
577    }
578
579    /**
580     * Gets the fraction of the current C/A code cycle.
581     * Range: [0, 1023]
582     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
583     * The reported code-phase includes {@link #getCodePhaseUncertaintyInChips()}.
584     *
585     * The value is only available if {@link #hasCodePhaseInChips()} is true.
586     */
587    public double getCodePhaseInChips() {
588        return mCodePhaseInChips;
589    }
590
591    /**
592     * Sets the Code-phase in chips.
593     */
594    public void setCodePhaseInChips(double value) {
595        setFlag(HAS_CODE_PHASE);
596        mCodePhaseInChips = value;
597    }
598
599    /**
600     * Resets the Code-phase in chips.
601     */
602    public void resetCodePhaseInChips() {
603        resetFlag(HAS_CODE_PHASE);
604        mCodePhaseInChips = Double.NaN;
605    }
606
607    /**
608     * Returns true if {@link #getCodePhaseUncertaintyInChips()} is available, false otherwise.
609     */
610    public boolean hasCodePhaseUncertaintyInChips() {
611        return isFlagSet(HAS_CODE_PHASE_UNCERTAINTY);
612    }
613
614    /**
615     * Gets the code-phase's uncertainty (1-Sigma) as a fraction of chips.
616     * The uncertainty is represented as an absolute (single sided) value.
617     *
618     * The value is only available if {@link #hasCodePhaseUncertaintyInChips()} is true.
619     */
620    public double getCodePhaseUncertaintyInChips() {
621        return mCodePhaseUncertaintyInChips;
622    }
623
624    /**
625     * Sets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
626     */
627    public void setCodePhaseUncertaintyInChips(double value) {
628        setFlag(HAS_CODE_PHASE_UNCERTAINTY);
629        mCodePhaseUncertaintyInChips = value;
630    }
631
632    /**
633     * Resets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
634     */
635    public void resetCodePhaseUncertaintyInChips() {
636        resetFlag(HAS_CODE_PHASE_UNCERTAINTY);
637        mCodePhaseUncertaintyInChips = Double.NaN;
638    }
639
640    /**
641     * Returns true if {@link #getCarrierFrequencyInHz()} is available, false otherwise.
642     */
643    public boolean hasCarrierFrequencyInHz() {
644        return isFlagSet(HAS_CARRIER_FREQUENCY);
645    }
646
647    /**
648     * Gets the carrier frequency at which codes and messages are modulated, it can be L1 or L2.
649     * If the field is not set, the carrier frequency corresponds to L1.
650     *
651     * The value is only available if {@link #hasCarrierFrequencyInHz()} is true.
652     */
653    public float getCarrierFrequencyInHz() {
654        return mCarrierFrequencyInHz;
655    }
656
657    /**
658     * Sets the Carrier frequency (L1 or L2) in Hz.
659     */
660    public void setCarrierFrequencyInHz(float carrierFrequencyInHz) {
661        setFlag(HAS_CARRIER_FREQUENCY);
662        mCarrierFrequencyInHz = carrierFrequencyInHz;
663    }
664
665    /**
666     * Resets the Carrier frequency (L1 or L2) in Hz.
667     */
668    public void resetCarrierFrequencyInHz() {
669        resetFlag(HAS_CARRIER_FREQUENCY);
670        mCarrierFrequencyInHz = Float.NaN;
671    }
672
673    /**
674     * Returns true if {@link #getCarrierCycles()} is available, false otherwise.
675     */
676    public boolean hasCarrierCycles() {
677        return isFlagSet(HAS_CARRIER_CYCLES);
678    }
679
680    /**
681     * The number of full carrier cycles between the satellite and the receiver.
682     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
683     *
684     * The value is only available if {@link #hasCarrierCycles()} is true.
685     */
686    public long getCarrierCycles() {
687        return mCarrierCycles;
688    }
689
690    /**
691     * Sets the number of full carrier cycles between the satellite and the receiver.
692     */
693    public void setCarrierCycles(long value) {
694        setFlag(HAS_CARRIER_CYCLES);
695        mCarrierCycles = value;
696    }
697
698    /**
699     * Resets the number of full carrier cycles between the satellite and the receiver.
700     */
701    public void resetCarrierCycles() {
702        resetFlag(HAS_CARRIER_CYCLES);
703        mCarrierCycles = Long.MIN_VALUE;
704    }
705
706    /**
707     * Returns true if {@link #getCarrierPhase()} is available, false otherwise.
708     */
709    public boolean hasCarrierPhase() {
710        return isFlagSet(HAS_CARRIER_PHASE);
711    }
712
713    /**
714     * Gets the RF phase detected by the receiver.
715     * Range: [0.0, 1.0].
716     * This is usually the fractional part of the complete carrier phase measurement.
717     *
718     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
719     * The reported carrier-phase includes {@link #getCarrierPhaseUncertainty()}.
720     *
721     * The value is only available if {@link #hasCarrierPhase()} is true.
722     */
723    public double getCarrierPhase() {
724        return mCarrierPhase;
725    }
726
727    /**
728     * Sets the RF phase detected by the receiver.
729     */
730    public void setCarrierPhase(double value) {
731        setFlag(HAS_CARRIER_PHASE);
732        mCarrierPhase = value;
733    }
734
735    /**
736     * Resets the RF phase detected by the receiver.
737     */
738    public void resetCarrierPhase() {
739        resetFlag(HAS_CARRIER_PHASE);
740        mCarrierPhase = Double.NaN;
741    }
742
743    /**
744     * Returns true if {@link #getCarrierPhaseUncertainty()} is available, false otherwise.
745     */
746    public boolean hasCarrierPhaseUncertainty() {
747        return isFlagSet(HAS_CARRIER_PHASE_UNCERTAINTY);
748    }
749
750    /**
751     * Gets the carrier-phase's uncertainty (1-Sigma).
752     * The uncertainty is represented as an absolute (single sided) value.
753     *
754     * The value is only available if {@link #hasCarrierPhaseUncertainty()} is true.
755     */
756    public double getCarrierPhaseUncertainty() {
757        return mCarrierPhaseUncertainty;
758    }
759
760    /**
761     * Sets the Carrier-phase's uncertainty (1-Sigma) in cycles.
762     */
763    public void setCarrierPhaseUncertainty(double value) {
764        setFlag(HAS_CARRIER_PHASE_UNCERTAINTY);
765        mCarrierPhaseUncertainty = value;
766    }
767
768    /**
769     * Resets the Carrier-phase's uncertainty (1-Sigma) in cycles.
770     */
771    public void resetCarrierPhaseUncertainty() {
772        resetFlag(HAS_CARRIER_PHASE_UNCERTAINTY);
773        mCarrierPhaseUncertainty = Double.NaN;
774    }
775
776    /**
777     * Gets a value indicating the 'loss of lock' state of the event.
778     */
779    public byte getLossOfLock() {
780        return mLossOfLock;
781    }
782
783    /**
784     * Sets the 'loss of lock' status.
785     */
786    public void setLossOfLock(byte value) {
787        mLossOfLock = value;
788    }
789
790    /**
791     * Gets a string representation of the 'loss of lock'.
792     * For internal and logging use only.
793     */
794    private String getLossOfLockString() {
795        switch (mLossOfLock) {
796            case LOSS_OF_LOCK_UNKNOWN:
797                return "Unknown";
798            case LOSS_OF_LOCK_OK:
799                return "Ok";
800            case LOSS_OF_LOCK_CYCLE_SLIP:
801                return "CycleSlip";
802            default:
803                return "<Invalid:" + mLossOfLock + ">";
804        }
805    }
806
807    /**
808     * Returns true if {@link #getBitNumber()} is available, false otherwise.
809     */
810    public boolean hasBitNumber() {
811        return isFlagSet(HAS_BIT_NUMBER);
812    }
813
814    /**
815     * Gets the number of GPS bits transmitted since Sat-Sun midnight (GPS week).
816     *
817     * The value is only available if {@link #hasBitNumber()} is true.
818     */
819    public int getBitNumber() {
820        return mBitNumber;
821    }
822
823    /**
824     * Sets the bit number within the broadcast frame.
825     */
826    public void setBitNumber(int bitNumber) {
827        setFlag(HAS_BIT_NUMBER);
828        mBitNumber = bitNumber;
829    }
830
831    /**
832     * Resets the bit number within the broadcast frame.
833     */
834    public void resetBitNumber() {
835        resetFlag(HAS_BIT_NUMBER);
836        mBitNumber = Integer.MIN_VALUE;
837    }
838
839    /**
840     * Returns true if {@link #getTimeFromLastBitInMs()} is available, false otherwise.
841     */
842    public boolean hasTimeFromLastBitInMs() {
843        return isFlagSet(HAS_TIME_FROM_LAST_BIT);
844    }
845
846    /**
847     * Gets the elapsed time since the last received bit in milliseconds.
848     * Range: [0, 20].
849     *
850     * The value is only available if {@link #hasTimeFromLastBitInMs()} is true.
851     */
852    public short getTimeFromLastBitInMs() {
853        return mTimeFromLastBitInMs;
854    }
855
856    /**
857     * Sets the elapsed time since the last received bit in milliseconds.
858     */
859    public void setTimeFromLastBitInMs(short value) {
860        setFlag(HAS_TIME_FROM_LAST_BIT);
861        mTimeFromLastBitInMs = value;
862    }
863
864    /**
865     * Resets the elapsed time since the last received bit in milliseconds.
866     */
867    public void resetTimeFromLastBitInMs() {
868        resetFlag(HAS_TIME_FROM_LAST_BIT);
869        mTimeFromLastBitInMs = Short.MIN_VALUE;
870    }
871
872    /**
873     * Returns true if {@link #getDopplerShiftInHz()} is available, false otherwise.
874     */
875    public boolean hasDopplerShiftInHz() {
876        return isFlagSet(HAS_DOPPLER_SHIFT);
877    }
878
879    /**
880     * Gets the Doppler Shift in Hz.
881     * A positive value indicates that the SV is moving toward the receiver.
882     *
883     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
884     * The reported doppler shift includes {@link #getDopplerShiftUncertaintyInHz()}.
885     *
886     * The value is only available if {@link #hasDopplerShiftInHz()} is true.
887     */
888    public double getDopplerShiftInHz() {
889        return mDopplerShiftInHz;
890    }
891
892    /**
893     * Sets the Doppler shift in Hz.
894     */
895    public void setDopplerShiftInHz(double value) {
896        setFlag(HAS_DOPPLER_SHIFT);
897        mDopplerShiftInHz = value;
898    }
899
900    /**
901     * Resets the Doppler shift in Hz.
902     */
903    public void resetDopplerShiftInHz() {
904        resetFlag(HAS_DOPPLER_SHIFT);
905        mDopplerShiftInHz = Double.NaN;
906    }
907
908    /**
909     * Returns true if {@link #getDopplerShiftUncertaintyInHz()} is available, false otherwise.
910     */
911    public boolean hasDopplerShiftUncertaintyInHz() {
912        return isFlagSet(HAS_DOPPLER_SHIFT_UNCERTAINTY);
913    }
914
915    /**
916     * Gets the Doppler's Shift uncertainty (1-Sigma) in Hz.
917     * The uncertainty is represented as an absolute (single sided) value.
918     *
919     * The value is only available if {@link #hasDopplerShiftUncertaintyInHz()} is true.
920     */
921    public double getDopplerShiftUncertaintyInHz() {
922        return mDopplerShiftUncertaintyInHz;
923    }
924
925    /**
926     * Sets the Doppler's shift uncertainty (1-Sigma) in Hz.
927     */
928    public void setDopplerShiftUncertaintyInHz(double value) {
929        setFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
930        mDopplerShiftUncertaintyInHz = value;
931    }
932
933    /**
934     * Resets the Doppler's shift uncertainty (1-Sigma) in Hz.
935     */
936    public void resetDopplerShiftUncertaintyInHz() {
937        resetFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
938        mDopplerShiftUncertaintyInHz = Double.NaN;
939    }
940
941    /**
942     * Gets a value indicating the 'multipath' state of the event.
943     */
944    public byte getMultipathIndicator() {
945        return mMultipathIndicator;
946    }
947
948    /**
949     * Sets the 'multi-path' indicator.
950     */
951    public void setMultipathIndicator(byte value) {
952        mMultipathIndicator = value;
953    }
954
955    /**
956     * Gets a string representation of the 'multi-path indicator'.
957     * For internal and logging use only.
958     */
959    private String getMultipathIndicatorString() {
960        switch(mMultipathIndicator) {
961            case MULTIPATH_INDICATOR_UNKNOWN:
962                return "Unknown";
963            case MULTIPATH_INDICATOR_DETECTED:
964                return "Detected";
965            case MULTIPATH_INDICATOR_NOT_USED:
966                return "NotUsed";
967            default:
968                return "<Invalid:" + mMultipathIndicator + ">";
969        }
970    }
971
972    /**
973     * Returns true if {@link #getSnrInDb()} is available, false otherwise.
974     */
975    public boolean hasSnrInDb() {
976        return isFlagSet(HAS_SNR);
977    }
978
979    /**
980     * Gets the Signal-to-Noise ratio (SNR) in dB.
981     *
982     * The value is only available if {@link #hasSnrInDb()} is true.
983     */
984    public double getSnrInDb() {
985        return mSnrInDb;
986    }
987
988    /**
989     * Sets the Signal-to-noise ratio (SNR) in dB.
990     */
991    public void setSnrInDb(double snrInDb) {
992        setFlag(HAS_SNR);
993        mSnrInDb = snrInDb;
994    }
995
996    /**
997     * Resets the Signal-to-noise ratio (SNR) in dB.
998     */
999    public void resetSnrInDb() {
1000        resetFlag(HAS_SNR);
1001        mSnrInDb = Double.NaN;
1002    }
1003
1004    /**
1005     * Returns true if {@link #getElevationInDeg()} is available, false otherwise.
1006     */
1007    public boolean hasElevationInDeg() {
1008        return isFlagSet(HAS_ELEVATION);
1009    }
1010
1011    /**
1012     * Gets the Elevation in degrees.
1013     * Range: [-90, 90]
1014     * The reported elevation includes {@link #getElevationUncertaintyInDeg()}.
1015     *
1016     * The value is only available if {@link #hasElevationInDeg()} is true.
1017     */
1018    public double getElevationInDeg() {
1019        return mElevationInDeg;
1020    }
1021
1022    /**
1023     * Sets the Elevation in degrees.
1024     */
1025    public void setElevationInDeg(double elevationInDeg) {
1026        setFlag(HAS_ELEVATION);
1027        mElevationInDeg = elevationInDeg;
1028    }
1029
1030    /**
1031     * Resets the Elevation in degrees.
1032     */
1033    public void resetElevationInDeg() {
1034        resetFlag(HAS_ELEVATION);
1035        mElevationInDeg = Double.NaN;
1036    }
1037
1038    /**
1039     * Returns true if {@link #getElevationUncertaintyInDeg()} is available, false otherwise.
1040     */
1041    public boolean hasElevationUncertaintyInDeg() {
1042        return isFlagSet(HAS_ELEVATION_UNCERTAINTY);
1043    }
1044
1045    /**
1046     * Gets the elevation's uncertainty (1-Sigma) in degrees.
1047     * Range: [0, 90]
1048     *
1049     * The uncertainty is represented as an absolute (single sided) value.
1050     *
1051     * The value is only available if {@link #hasElevationUncertaintyInDeg()} is true.
1052     */
1053    public double getElevationUncertaintyInDeg() {
1054        return mElevationUncertaintyInDeg;
1055    }
1056
1057    /**
1058     * Sets the elevation's uncertainty (1-Sigma) in degrees.
1059     */
1060    public void setElevationUncertaintyInDeg(double value) {
1061        setFlag(HAS_ELEVATION_UNCERTAINTY);
1062        mElevationUncertaintyInDeg = value;
1063    }
1064
1065    /**
1066     * Resets the elevation's uncertainty (1-Sigma) in degrees.
1067     */
1068    public void resetElevationUncertaintyInDeg() {
1069        resetFlag(HAS_ELEVATION_UNCERTAINTY);
1070        mElevationUncertaintyInDeg = Double.NaN;
1071    }
1072
1073    /**
1074     * Returns true if {@link #getAzimuthInDeg()} is available, false otherwise.
1075     */
1076    public boolean hasAzimuthInDeg() {
1077        return isFlagSet(HAS_AZIMUTH);
1078    }
1079
1080    /**
1081     * Gets the azimuth in degrees.
1082     * Range: [0, 360).
1083     *
1084     * The reported azimuth includes {@link #getAzimuthUncertaintyInDeg()}.
1085     *
1086     * The value is only available if {@link #hasAzimuthInDeg()} is true.
1087     */
1088    public double getAzimuthInDeg() {
1089        return mAzimuthInDeg;
1090    }
1091
1092    /**
1093     * Sets the Azimuth in degrees.
1094     */
1095    public void setAzimuthInDeg(double value) {
1096        setFlag(HAS_AZIMUTH);
1097        mAzimuthInDeg = value;
1098    }
1099
1100    /**
1101     * Resets the Azimuth in degrees.
1102     */
1103    public void resetAzimuthInDeg() {
1104        resetFlag(HAS_AZIMUTH);
1105        mAzimuthInDeg = Double.NaN;
1106    }
1107
1108    /**
1109     * Returns true if {@link #getAzimuthUncertaintyInDeg()} is available, false otherwise.
1110     */
1111    public boolean hasAzimuthUncertaintyInDeg() {
1112        return isFlagSet(HAS_AZIMUTH_UNCERTAINTY);
1113    }
1114
1115    /**
1116     * Gets the azimuth's uncertainty (1-Sigma) in degrees.
1117     * Range: [0, 180].
1118     *
1119     * The uncertainty is represented as an absolute (single sided) value.
1120     *
1121     * The value is only available if {@link #hasAzimuthUncertaintyInDeg()} is true.
1122     */
1123    public double getAzimuthUncertaintyInDeg() {
1124        return mAzimuthUncertaintyInDeg;
1125    }
1126
1127    /**
1128     * Sets the Azimuth's uncertainty (1-Sigma) in degrees.
1129     */
1130    public void setAzimuthUncertaintyInDeg(double value) {
1131        setFlag(HAS_AZIMUTH_UNCERTAINTY);
1132        mAzimuthUncertaintyInDeg = value;
1133    }
1134
1135    /**
1136     * Resets the Azimuth's uncertainty (1-Sigma) in degrees.
1137     */
1138    public void resetAzimuthUncertaintyInDeg() {
1139        resetFlag(HAS_AZIMUTH_UNCERTAINTY);
1140        mAzimuthUncertaintyInDeg = Double.NaN;
1141    }
1142
1143    /**
1144     * Gets a flag indicating whether the GPS represented by the measurement was used for computing
1145     * the most recent fix.
1146     *
1147     * @return A non-null value if the data is available, null otherwise.
1148     */
1149    public boolean isUsedInFix() {
1150        return mUsedInFix;
1151    }
1152
1153    /**
1154     * Sets the Used-in-Fix flag.
1155     */
1156    public void setUsedInFix(boolean value) {
1157        mUsedInFix = value;
1158    }
1159
1160    public static final Creator<GpsMeasurement> CREATOR = new Creator<GpsMeasurement>() {
1161        @Override
1162        public GpsMeasurement createFromParcel(Parcel parcel) {
1163            GpsMeasurement gpsMeasurement = new GpsMeasurement();
1164
1165            gpsMeasurement.mFlags = parcel.readInt();
1166            gpsMeasurement.mPrn = parcel.readByte();
1167            gpsMeasurement.mTimeOffsetInNs = parcel.readDouble();
1168            gpsMeasurement.mState = (short) parcel.readInt();
1169            gpsMeasurement.mReceivedGpsTowInNs = parcel.readLong();
1170            gpsMeasurement.mReceivedGpsTowUncertaintyInNs = parcel.readLong();
1171            gpsMeasurement.mCn0InDbHz = parcel.readDouble();
1172            gpsMeasurement.mPseudorangeRateInMetersPerSec = parcel.readDouble();
1173            gpsMeasurement.mPseudorangeRateUncertaintyInMetersPerSec = parcel.readDouble();
1174            gpsMeasurement.mAccumulatedDeltaRangeState = (short) parcel.readInt();
1175            gpsMeasurement.mAccumulatedDeltaRangeInMeters = parcel.readDouble();
1176            gpsMeasurement.mAccumulatedDeltaRangeUncertaintyInMeters = parcel.readDouble();
1177            gpsMeasurement.mPseudorangeInMeters = parcel.readDouble();
1178            gpsMeasurement.mPseudorangeUncertaintyInMeters = parcel.readDouble();
1179            gpsMeasurement.mCodePhaseInChips = parcel.readDouble();
1180            gpsMeasurement.mCodePhaseUncertaintyInChips = parcel.readDouble();
1181            gpsMeasurement.mCarrierFrequencyInHz = parcel.readFloat();
1182            gpsMeasurement.mCarrierCycles = parcel.readLong();
1183            gpsMeasurement.mCarrierPhase = parcel.readDouble();
1184            gpsMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
1185            gpsMeasurement.mLossOfLock = parcel.readByte();
1186            gpsMeasurement.mBitNumber = parcel.readInt();
1187            gpsMeasurement.mTimeFromLastBitInMs = (short) parcel.readInt();
1188            gpsMeasurement.mDopplerShiftInHz = parcel.readDouble();
1189            gpsMeasurement.mDopplerShiftUncertaintyInHz = parcel.readDouble();
1190            gpsMeasurement.mMultipathIndicator = parcel.readByte();
1191            gpsMeasurement.mSnrInDb = parcel.readDouble();
1192            gpsMeasurement.mElevationInDeg = parcel.readDouble();
1193            gpsMeasurement.mElevationUncertaintyInDeg = parcel.readDouble();
1194            gpsMeasurement.mAzimuthInDeg = parcel.readDouble();
1195            gpsMeasurement.mAzimuthUncertaintyInDeg = parcel.readDouble();
1196            gpsMeasurement.mUsedInFix = parcel.readInt() != 0;
1197
1198            return gpsMeasurement;
1199        }
1200
1201        @Override
1202        public GpsMeasurement[] newArray(int i) {
1203            return new GpsMeasurement[i];
1204        }
1205    };
1206
1207    public void writeToParcel(Parcel parcel, int flags) {
1208        parcel.writeInt(mFlags);
1209        parcel.writeByte(mPrn);
1210        parcel.writeDouble(mTimeOffsetInNs);
1211        parcel.writeInt(mState);
1212        parcel.writeLong(mReceivedGpsTowInNs);
1213        parcel.writeLong(mReceivedGpsTowUncertaintyInNs);
1214        parcel.writeDouble(mCn0InDbHz);
1215        parcel.writeDouble(mPseudorangeRateInMetersPerSec);
1216        parcel.writeDouble(mPseudorangeRateUncertaintyInMetersPerSec);
1217        parcel.writeInt(mAccumulatedDeltaRangeState);
1218        parcel.writeDouble(mAccumulatedDeltaRangeInMeters);
1219        parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyInMeters);
1220        parcel.writeDouble(mPseudorangeInMeters);
1221        parcel.writeDouble(mPseudorangeUncertaintyInMeters);
1222        parcel.writeDouble(mCodePhaseInChips);
1223        parcel.writeDouble(mCodePhaseUncertaintyInChips);
1224        parcel.writeFloat(mCarrierFrequencyInHz);
1225        parcel.writeLong(mCarrierCycles);
1226        parcel.writeDouble(mCarrierPhase);
1227        parcel.writeDouble(mCarrierPhaseUncertainty);
1228        parcel.writeByte(mLossOfLock);
1229        parcel.writeInt(mBitNumber);
1230        parcel.writeInt(mTimeFromLastBitInMs);
1231        parcel.writeDouble(mDopplerShiftInHz);
1232        parcel.writeDouble(mDopplerShiftUncertaintyInHz);
1233        parcel.writeByte(mMultipathIndicator);
1234        parcel.writeDouble(mSnrInDb);
1235        parcel.writeDouble(mElevationInDeg);
1236        parcel.writeDouble(mElevationUncertaintyInDeg);
1237        parcel.writeDouble(mAzimuthInDeg);
1238        parcel.writeDouble(mAzimuthUncertaintyInDeg);
1239        parcel.writeInt(mUsedInFix ? 1 : 0);
1240    }
1241
1242    @Override
1243    public int describeContents() {
1244        return 0;
1245    }
1246
1247    @Override
1248    public String toString() {
1249        final String format = "   %-29s = %s\n";
1250        final String formatWithUncertainty = "   %-29s = %-25s   %-40s = %s\n";
1251        StringBuilder builder = new StringBuilder("GpsMeasurement:\n");
1252
1253        builder.append(String.format(format, "Prn", mPrn));
1254
1255        builder.append(String.format(format, "TimeOffsetInNs", mTimeOffsetInNs));
1256
1257        builder.append(String.format(format, "State", getStateString()));
1258
1259        builder.append(String.format(
1260                formatWithUncertainty,
1261                "ReceivedGpsTowInNs",
1262                mReceivedGpsTowInNs,
1263                "ReceivedGpsTowUncertaintyInNs",
1264                mReceivedGpsTowUncertaintyInNs));
1265
1266        builder.append(String.format(format, "Cn0InDbHz", mCn0InDbHz));
1267
1268        builder.append(String.format(
1269                formatWithUncertainty,
1270                "PseudorangeRateInMetersPerSec",
1271                mPseudorangeRateInMetersPerSec,
1272                "PseudorangeRateUncertaintyInMetersPerSec",
1273                mPseudorangeRateUncertaintyInMetersPerSec));
1274        builder.append(String.format(
1275                format,
1276                "PseudorangeRateIsCorrected",
1277                isPseudorangeRateCorrected()));
1278
1279        builder.append(String.format(
1280                format,
1281                "AccumulatedDeltaRangeState",
1282                getAccumulatedDeltaRangeStateString()));
1283
1284        builder.append(String.format(
1285                formatWithUncertainty,
1286                "AccumulatedDeltaRangeInMeters",
1287                mAccumulatedDeltaRangeInMeters,
1288                "AccumulatedDeltaRangeUncertaintyInMeters",
1289                mAccumulatedDeltaRangeUncertaintyInMeters));
1290
1291        builder.append(String.format(
1292                formatWithUncertainty,
1293                "PseudorangeInMeters",
1294                hasPseudorangeInMeters() ? mPseudorangeInMeters : null,
1295                "PseudorangeUncertaintyInMeters",
1296                hasPseudorangeUncertaintyInMeters() ? mPseudorangeUncertaintyInMeters : null));
1297
1298        builder.append(String.format(
1299                formatWithUncertainty,
1300                "CodePhaseInChips",
1301                hasCodePhaseInChips() ? mCodePhaseInChips : null,
1302                "CodePhaseUncertaintyInChips",
1303                hasCodePhaseUncertaintyInChips() ? mCodePhaseUncertaintyInChips : null));
1304
1305        builder.append(String.format(
1306                format,
1307                "CarrierFrequencyInHz",
1308                hasCarrierFrequencyInHz() ? mCarrierFrequencyInHz : null));
1309
1310        builder.append(String.format(
1311                format,
1312                "CarrierCycles",
1313                hasCarrierCycles() ? mCarrierCycles : null));
1314
1315        builder.append(String.format(
1316                formatWithUncertainty,
1317                "CarrierPhase",
1318                hasCarrierPhase() ? mCarrierPhase : null,
1319                "CarrierPhaseUncertainty",
1320                hasCarrierPhaseUncertainty() ? mCarrierPhaseUncertainty : null));
1321
1322        builder.append(String.format(format, "LossOfLock", getLossOfLockString()));
1323
1324        builder.append(String.format(
1325                format,
1326                "BitNumber",
1327                hasBitNumber() ? mBitNumber : null));
1328
1329        builder.append(String.format(
1330                format,
1331                "TimeFromLastBitInMs",
1332                hasTimeFromLastBitInMs() ? mTimeFromLastBitInMs : null));
1333
1334        builder.append(String.format(
1335                formatWithUncertainty,
1336                "DopplerShiftInHz",
1337                hasDopplerShiftInHz() ? mDopplerShiftInHz : null,
1338                "DopplerShiftUncertaintyInHz",
1339                hasDopplerShiftUncertaintyInHz() ? mDopplerShiftUncertaintyInHz : null));
1340
1341        builder.append(String.format(format, "MultipathIndicator", getMultipathIndicatorString()));
1342
1343        builder.append(String.format(
1344                format,
1345                "SnrInDb",
1346                hasSnrInDb() ? mSnrInDb : null));
1347
1348        builder.append(String.format(
1349                formatWithUncertainty,
1350                "ElevationInDeg",
1351                hasElevationInDeg() ? mElevationInDeg : null,
1352                "ElevationUncertaintyInDeg",
1353                hasElevationUncertaintyInDeg() ? mElevationUncertaintyInDeg : null));
1354
1355        builder.append(String.format(
1356                formatWithUncertainty,
1357                "AzimuthInDeg",
1358                hasAzimuthInDeg() ? mAzimuthInDeg : null,
1359                "AzimuthUncertaintyInDeg",
1360                hasAzimuthUncertaintyInDeg() ? mAzimuthUncertaintyInDeg : null));
1361
1362        builder.append(String.format(format, "UsedInFix", mUsedInFix));
1363
1364        return builder.toString();
1365    }
1366
1367    private void initialize() {
1368        mFlags = HAS_NO_FLAGS;
1369        setPrn(Byte.MIN_VALUE);
1370        setTimeOffsetInNs(Long.MIN_VALUE);
1371        setState(STATE_UNKNOWN);
1372        setReceivedGpsTowInNs(Long.MIN_VALUE);
1373        setReceivedGpsTowUncertaintyInNs(Long.MAX_VALUE);
1374        setCn0InDbHz(Double.MIN_VALUE);
1375        setPseudorangeRateInMetersPerSec(Double.MIN_VALUE);
1376        setPseudorangeRateUncertaintyInMetersPerSec(Double.MIN_VALUE);
1377        setAccumulatedDeltaRangeState(ADR_STATE_UNKNOWN);
1378        setAccumulatedDeltaRangeInMeters(Double.MIN_VALUE);
1379        setAccumulatedDeltaRangeUncertaintyInMeters(Double.MIN_VALUE);
1380        resetPseudorangeInMeters();
1381        resetPseudorangeUncertaintyInMeters();
1382        resetCodePhaseInChips();
1383        resetCodePhaseUncertaintyInChips();
1384        resetCarrierFrequencyInHz();
1385        resetCarrierCycles();
1386        resetCarrierPhase();
1387        resetCarrierPhaseUncertainty();
1388        setLossOfLock(LOSS_OF_LOCK_UNKNOWN);
1389        resetBitNumber();
1390        resetTimeFromLastBitInMs();
1391        resetDopplerShiftInHz();
1392        resetDopplerShiftUncertaintyInHz();
1393        setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
1394        resetSnrInDb();
1395        resetElevationInDeg();
1396        resetElevationUncertaintyInDeg();
1397        resetAzimuthInDeg();
1398        resetAzimuthUncertaintyInDeg();
1399        setUsedInFix(false);
1400    }
1401
1402    private void setFlag(int flag) {
1403        mFlags |= flag;
1404    }
1405
1406    private void resetFlag(int flag) {
1407        mFlags &= ~flag;
1408    }
1409
1410    private boolean isFlagSet(int flag) {
1411        return (mFlags & flag) == flag;
1412    }
1413}
1414