Home | History | Annotate | Download | only in location
      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 
     17 package android.location;
     18 
     19 import android.annotation.SystemApi;
     20 import android.os.Parcel;
     21 import android.os.Parcelable;
     22 
     23 /**
     24  * A class containing a GPS clock timestamp.
     25  * It represents a measurement of the GPS receiver's clock.
     26  *
     27  * @hide
     28  */
     29 @SystemApi
     30 public class GpsClock implements Parcelable {
     31 
     32     // The following enumerations must be in sync with the values declared in gps.h
     33 
     34     /**
     35      * The type of the time stored is not available or it is unknown.
     36      */
     37     public static final byte TYPE_UNKNOWN = 0;
     38 
     39     /**
     40      * The source of the time value reported by this class is the 'Local Hardware Clock'.
     41      */
     42     public static final byte TYPE_LOCAL_HW_TIME = 1;
     43 
     44     /**
     45      * The source of the time value reported by this class is the 'GPS time' derived from
     46      * satellites (epoch = Jan 6, 1980).
     47      */
     48     public static final byte TYPE_GPS_TIME = 2;
     49 
     50     private static final short HAS_NO_FLAGS = 0;
     51     private static final short HAS_LEAP_SECOND = (1<<0);
     52     private static final short HAS_TIME_UNCERTAINTY = (1<<1);
     53     private static final short HAS_FULL_BIAS = (1<<2);
     54     private static final short HAS_BIAS = (1<<3);
     55     private static final short HAS_BIAS_UNCERTAINTY = (1<<4);
     56     private static final short HAS_DRIFT = (1<<5);
     57     private static final short HAS_DRIFT_UNCERTAINTY = (1<<6);
     58 
     59     // End enumerations in sync with gps.h
     60 
     61     private short mFlags;
     62     private short mLeapSecond;
     63     private byte mType;
     64     private long mTimeInNs;
     65     private double mTimeUncertaintyInNs;
     66     private long mFullBiasInNs;
     67     private double mBiasInNs;
     68     private double mBiasUncertaintyInNs;
     69     private double mDriftInNsPerSec;
     70     private double mDriftUncertaintyInNsPerSec;
     71 
     72     GpsClock() {
     73         initialize();
     74     }
     75 
     76     /**
     77      * Sets all contents to the values stored in the provided object.
     78      */
     79     public void set(GpsClock clock) {
     80         mFlags = clock.mFlags;
     81         mLeapSecond = clock.mLeapSecond;
     82         mType = clock.mType;
     83         mTimeInNs = clock.mTimeInNs;
     84         mTimeUncertaintyInNs = clock.mTimeUncertaintyInNs;
     85         mFullBiasInNs = clock.mFullBiasInNs;
     86         mBiasInNs = clock.mBiasInNs;
     87         mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs;
     88         mDriftInNsPerSec = clock.mDriftInNsPerSec;
     89         mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec;
     90     }
     91 
     92     /**
     93      * Resets all the contents to its original state.
     94      */
     95     public void reset() {
     96         initialize();
     97     }
     98 
     99     /**
    100      * Gets the type of time reported by {@link #getTimeInNs()}.
    101      */
    102     public byte getType() {
    103         return mType;
    104     }
    105 
    106     /**
    107      * Sets the type of time reported.
    108      */
    109     public void setType(byte value) {
    110         mType = value;
    111     }
    112 
    113     /**
    114      * Gets a string representation of the 'type'.
    115      * For internal and logging use only.
    116      */
    117     private String getTypeString() {
    118         switch (mType) {
    119             case TYPE_UNKNOWN:
    120                 return "Unknown";
    121             case TYPE_GPS_TIME:
    122                 return "GpsTime";
    123             case TYPE_LOCAL_HW_TIME:
    124                 return "LocalHwClock";
    125             default:
    126                 return "<Invalid:" + mType + ">";
    127         }
    128     }
    129 
    130     /**
    131      * Returns true if {@link #getLeapSecond()} is available, false otherwise.
    132      */
    133     public boolean hasLeapSecond() {
    134         return isFlagSet(HAS_LEAP_SECOND);
    135     }
    136 
    137     /**
    138      * Gets the leap second associated with the clock's time.
    139      * The sign of the value is defined by the following equation:
    140      *      utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000
    141      *
    142      * The value is only available if {@link #hasLeapSecond()} is true.
    143      */
    144     public short getLeapSecond() {
    145         return mLeapSecond;
    146     }
    147 
    148     /**
    149      * Sets the leap second associated with the clock's time.
    150      */
    151     public void setLeapSecond(short leapSecond) {
    152         setFlag(HAS_LEAP_SECOND);
    153         mLeapSecond = leapSecond;
    154     }
    155 
    156     /**
    157      * Resets the leap second associated with the clock's time.
    158      */
    159     public void resetLeapSecond() {
    160         resetFlag(HAS_LEAP_SECOND);
    161         mLeapSecond = Short.MIN_VALUE;
    162     }
    163 
    164     /**
    165      * Gets the GPS receiver internal clock value in nanoseconds.
    166      * This can be either the 'local hardware clock' value ({@link #TYPE_LOCAL_HW_TIME}), or the
    167      * current GPS time derived inside GPS receiver ({@link #TYPE_GPS_TIME}).
    168      * {@link #getType()} defines the time reported.
    169      *
    170      * For 'local hardware clock' this value is expected to be monotonically increasing during the
    171      * reporting session. The real GPS time can be derived by compensating
    172      * {@link #getFullBiasInNs()} (when it is available) from this value.
    173      *
    174      * For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS
    175      * receiver can achieve. {@link #getTimeUncertaintyInNs()} should be available when GPS time is
    176      * specified.
    177      *
    178      * Sub-nanosecond accuracy can be provided by means of {@link #getBiasInNs()}.
    179      * The reported time includes {@link #getTimeUncertaintyInNs()}.
    180      */
    181     public long getTimeInNs() {
    182         return mTimeInNs;
    183     }
    184 
    185     /**
    186      * Sets the GPS receiver internal clock in nanoseconds.
    187      */
    188     public void setTimeInNs(long timeInNs) {
    189         mTimeInNs = timeInNs;
    190     }
    191 
    192     /**
    193      * Returns true if {@link #getTimeUncertaintyInNs()} is available, false otherwise.
    194      */
    195     public boolean hasTimeUncertaintyInNs() {
    196         return isFlagSet(HAS_TIME_UNCERTAINTY);
    197     }
    198 
    199     /**
    200      * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
    201      * The uncertainty is represented as an absolute (single sided) value.
    202      *
    203      * The value is only available if {@link #hasTimeUncertaintyInNs()} is true.
    204      */
    205     public double getTimeUncertaintyInNs() {
    206         return mTimeUncertaintyInNs;
    207     }
    208 
    209     /**
    210      * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
    211      */
    212     public void setTimeUncertaintyInNs(double timeUncertaintyInNs) {
    213         setFlag(HAS_TIME_UNCERTAINTY);
    214         mTimeUncertaintyInNs = timeUncertaintyInNs;
    215     }
    216 
    217     /**
    218      * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
    219      */
    220     public void resetTimeUncertaintyInNs() {
    221         resetFlag(HAS_TIME_UNCERTAINTY);
    222         mTimeUncertaintyInNs = Double.NaN;
    223     }
    224 
    225     /**
    226      * Returns true if {@link @getFullBiasInNs()} is available, false otherwise.
    227      */
    228     public boolean hasFullBiasInNs() {
    229         return isFlagSet(HAS_FULL_BIAS);
    230     }
    231 
    232     /**
    233      * Gets the difference between hardware clock ({@link #getTimeInNs()}) inside GPS receiver and
    234      * the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
    235      *
    236      * This value is available if {@link #TYPE_LOCAL_HW_TIME} is set, and GPS receiver has solved
    237      * the clock for GPS time.
    238      * {@link #getBiasUncertaintyInNs()} should be used for quality check.
    239      *
    240      * The sign of the value is defined by the following equation:
    241      *      true time (GPS time) = time_ns + (full_bias_ns + bias_ns)
    242      *
    243      * The reported full bias includes {@link #getBiasUncertaintyInNs()}.
    244      * The value is onl available if {@link #hasFullBiasInNs()} is true.
    245      */
    246     public long getFullBiasInNs() {
    247         return mFullBiasInNs;
    248     }
    249 
    250     /**
    251      * Sets the full bias in nanoseconds.
    252      */
    253     public void setFullBiasInNs(long value) {
    254         setFlag(HAS_FULL_BIAS);
    255         mFullBiasInNs = value;
    256     }
    257 
    258     /**
    259      * Resets the full bias in nanoseconds.
    260      */
    261     public void resetFullBiasInNs() {
    262         resetFlag(HAS_FULL_BIAS);
    263         mFullBiasInNs = Long.MIN_VALUE;
    264     }
    265 
    266     /**
    267      * Returns true if {@link #getBiasInNs()} is available, false otherwise.
    268      */
    269     public boolean hasBiasInNs() {
    270         return isFlagSet(HAS_BIAS);
    271     }
    272 
    273     /**
    274      * Gets the clock's sub-nanosecond bias.
    275      * The reported bias includes {@link #getBiasUncertaintyInNs()}.
    276      *
    277      * The value is only available if {@link #hasBiasInNs()} is true.
    278      */
    279     public double getBiasInNs() {
    280         return mBiasInNs;
    281     }
    282 
    283     /**
    284      * Sets the sub-nanosecond bias.
    285      */
    286     public void setBiasInNs(double biasInNs) {
    287         setFlag(HAS_BIAS);
    288         mBiasInNs = biasInNs;
    289     }
    290 
    291     /**
    292      * Resets the clock's Bias in nanoseconds.
    293      */
    294     public void resetBiasInNs() {
    295         resetFlag(HAS_BIAS);
    296         mBiasInNs = Double.NaN;
    297     }
    298 
    299     /**
    300      * Returns true if {@link #getBiasUncertaintyInNs()} is available, false otherwise.
    301      */
    302     public boolean hasBiasUncertaintyInNs() {
    303         return isFlagSet(HAS_BIAS_UNCERTAINTY);
    304     }
    305 
    306     /**
    307      * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
    308      *
    309      * The value is only available if {@link #hasBiasUncertaintyInNs()} is true.
    310      */
    311     public double getBiasUncertaintyInNs() {
    312         return mBiasUncertaintyInNs;
    313     }
    314 
    315     /**
    316      * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
    317      */
    318     public void setBiasUncertaintyInNs(double biasUncertaintyInNs) {
    319         setFlag(HAS_BIAS_UNCERTAINTY);
    320         mBiasUncertaintyInNs = biasUncertaintyInNs;
    321     }
    322 
    323     /**
    324      * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
    325      */
    326     public void resetBiasUncertaintyInNs() {
    327         resetFlag(HAS_BIAS_UNCERTAINTY);
    328         mBiasUncertaintyInNs = Double.NaN;
    329     }
    330 
    331     /**
    332      * Returns true if {@link #getDriftInNsPerSec()} is available, false otherwise.
    333      */
    334     public boolean hasDriftInNsPerSec() {
    335         return isFlagSet(HAS_DRIFT);
    336     }
    337 
    338     /**
    339      * Gets the clock's Drift in nanoseconds per second.
    340      * A positive value indicates that the frequency is higher than the nominal frequency.
    341      * The reported drift includes {@link #getDriftUncertaintyInNsPerSec()}.
    342      *
    343      * The value is only available if {@link #hasDriftInNsPerSec()} is true.
    344      */
    345     public double getDriftInNsPerSec() {
    346         return mDriftInNsPerSec;
    347     }
    348 
    349     /**
    350      * Sets the clock's Drift in nanoseconds per second.
    351      */
    352     public void setDriftInNsPerSec(double driftInNsPerSec) {
    353         setFlag(HAS_DRIFT);
    354         mDriftInNsPerSec = driftInNsPerSec;
    355     }
    356 
    357     /**
    358      * Resets the clock's Drift in nanoseconds per second.
    359      */
    360     public void resetDriftInNsPerSec() {
    361         resetFlag(HAS_DRIFT);
    362         mDriftInNsPerSec = Double.NaN;
    363     }
    364 
    365     /**
    366      * Returns true if {@link #getDriftUncertaintyInNsPerSec()} is available, false otherwise.
    367      */
    368     public boolean hasDriftUncertaintyInNsPerSec() {
    369         return isFlagSet(HAS_DRIFT_UNCERTAINTY);
    370     }
    371 
    372     /**
    373      * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
    374      *
    375      * The value is only available if {@link #hasDriftUncertaintyInNsPerSec()} is true.
    376      */
    377     public double getDriftUncertaintyInNsPerSec() {
    378         return mDriftUncertaintyInNsPerSec;
    379     }
    380 
    381     /**
    382      * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
    383      */
    384     public void setDriftUncertaintyInNsPerSec(double driftUncertaintyInNsPerSec) {
    385         setFlag(HAS_DRIFT_UNCERTAINTY);
    386         mDriftUncertaintyInNsPerSec = driftUncertaintyInNsPerSec;
    387     }
    388 
    389     /**
    390      * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
    391      */
    392     public void resetDriftUncertaintyInNsPerSec() {
    393         resetFlag(HAS_DRIFT_UNCERTAINTY);
    394         mDriftUncertaintyInNsPerSec = Double.NaN;
    395     }
    396 
    397     public static final Creator<GpsClock> CREATOR = new Creator<GpsClock>() {
    398         @Override
    399         public GpsClock createFromParcel(Parcel parcel) {
    400             GpsClock gpsClock = new GpsClock();
    401 
    402             gpsClock.mFlags = (short) parcel.readInt();
    403             gpsClock.mLeapSecond = (short) parcel.readInt();
    404             gpsClock.mType = parcel.readByte();
    405             gpsClock.mTimeInNs = parcel.readLong();
    406             gpsClock.mTimeUncertaintyInNs = parcel.readDouble();
    407             gpsClock.mFullBiasInNs = parcel.readLong();
    408             gpsClock.mBiasInNs = parcel.readDouble();
    409             gpsClock.mBiasUncertaintyInNs = parcel.readDouble();
    410             gpsClock.mDriftInNsPerSec = parcel.readDouble();
    411             gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble();
    412 
    413             return gpsClock;
    414         }
    415 
    416         @Override
    417         public GpsClock[] newArray(int size) {
    418             return new GpsClock[size];
    419         }
    420     };
    421 
    422     public void writeToParcel(Parcel parcel, int flags) {
    423         parcel.writeInt(mFlags);
    424         parcel.writeInt(mLeapSecond);
    425         parcel.writeByte(mType);
    426         parcel.writeLong(mTimeInNs);
    427         parcel.writeDouble(mTimeUncertaintyInNs);
    428         parcel.writeLong(mFullBiasInNs);
    429         parcel.writeDouble(mBiasInNs);
    430         parcel.writeDouble(mBiasUncertaintyInNs);
    431         parcel.writeDouble(mDriftInNsPerSec);
    432         parcel.writeDouble(mDriftUncertaintyInNsPerSec);
    433     }
    434 
    435     @Override
    436     public int describeContents() {
    437         return 0;
    438     }
    439 
    440     @Override
    441     public String toString() {
    442         final String format = "   %-15s = %s\n";
    443         final String formatWithUncertainty = "   %-15s = %-25s   %-26s = %s\n";
    444         StringBuilder builder = new StringBuilder("GpsClock:\n");
    445 
    446         builder.append(String.format(format, "Type", getTypeString()));
    447 
    448         builder.append(String.format(format, "LeapSecond", hasLeapSecond() ? mLeapSecond : null));
    449 
    450         builder.append(String.format(
    451                 formatWithUncertainty,
    452                 "TimeInNs",
    453                 mTimeInNs,
    454                 "TimeUncertaintyInNs",
    455                 hasTimeUncertaintyInNs() ? mTimeUncertaintyInNs : null));
    456 
    457         builder.append(String.format(
    458                 format,
    459                 "FullBiasInNs",
    460                 hasFullBiasInNs() ? mFullBiasInNs : null));
    461 
    462         builder.append(String.format(
    463                 formatWithUncertainty,
    464                 "BiasInNs",
    465                 hasBiasInNs() ? mBiasInNs : null,
    466                 "BiasUncertaintyInNs",
    467                 hasBiasUncertaintyInNs() ? mBiasUncertaintyInNs : null));
    468 
    469         builder.append(String.format(
    470                 formatWithUncertainty,
    471                 "DriftInNsPerSec",
    472                 hasDriftInNsPerSec() ? mDriftInNsPerSec : null,
    473                 "DriftUncertaintyInNsPerSec",
    474                 hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null));
    475 
    476         return builder.toString();
    477     }
    478 
    479     private void initialize() {
    480         mFlags = HAS_NO_FLAGS;
    481         resetLeapSecond();
    482         setType(TYPE_UNKNOWN);
    483         setTimeInNs(Long.MIN_VALUE);
    484         resetTimeUncertaintyInNs();
    485         resetFullBiasInNs();
    486         resetBiasInNs();
    487         resetBiasUncertaintyInNs();
    488         resetDriftInNsPerSec();
    489         resetDriftUncertaintyInNsPerSec();
    490     }
    491 
    492     private void setFlag(short flag) {
    493         mFlags |= flag;
    494     }
    495 
    496     private void resetFlag(short flag) {
    497         mFlags &= ~flag;
    498     }
    499 
    500     private boolean isFlagSet(short flag) {
    501         return (mFlags & flag) == flag;
    502     }
    503 }
    504