Home | History | Annotate | Download | only in core
      1 /* Copyright (c) 2017, The Linux Foundation. All rights reserved.
      2  *
      3  * Redistribution and use in source and binary forms, with or without
      4  * modification, are permitted provided that the following conditions are
      5  * met:
      6  *     * Redistributions of source code must retain the above copyright
      7  *       notice, this list of conditions and the following disclaimer.
      8  *     * Redistributions in binary form must reproduce the above
      9  *       copyright notice, this list of conditions and the following
     10  *       disclaimer in the documentation and/or other materials provided
     11  *       with the distribution.
     12  *     * Neither the name of The Linux Foundation, nor the names of its
     13  *       contributors may be used to endorse or promote products derived
     14  *       from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  *
     28  */
     29 #define LOG_TAG "LocSvc_SystemStatus"
     30 
     31 #include <string>
     32 #include <stdlib.h>
     33 #include <string.h>
     34 #include <sys/time.h>
     35 #include <pthread.h>
     36 #include <platform_lib_log_util.h>
     37 #include <loc_nmea.h>
     38 #include <SystemStatus.h>
     39 
     40 namespace loc_core
     41 {
     42 
     43 /******************************************************************************
     44  SystemStatusNmeaBase - base class for all NMEA parsers
     45 ******************************************************************************/
     46 class SystemStatusNmeaBase
     47 {
     48 protected:
     49     std::vector<std::string> mField;
     50 
     51     SystemStatusNmeaBase(const char *str_in, uint32_t len_in)
     52     {
     53         // check size and talker
     54         if (!loc_nmea_is_debug(str_in, len_in)) {
     55             return;
     56         }
     57 
     58         std::string parser(str_in);
     59         std::string::size_type index = 0;
     60 
     61         // verify checksum field
     62         index = parser.find("*");
     63         if (index == std::string::npos) {
     64             return;
     65         }
     66         parser[index] = ',';
     67 
     68         // tokenize parser
     69         while (1) {
     70             std::string str;
     71             index = parser.find(",");
     72             if (index == std::string::npos) {
     73                 break;
     74             }
     75             str = parser.substr(0, index);
     76             parser = parser.substr(index + 1);
     77             mField.push_back(str);
     78         }
     79     }
     80 
     81     virtual ~SystemStatusNmeaBase() { }
     82 
     83 public:
     84     static const uint32_t NMEA_MINSIZE = DEBUG_NMEA_MINSIZE;
     85     static const uint32_t NMEA_MAXSIZE = DEBUG_NMEA_MAXSIZE;
     86 };
     87 
     88 /******************************************************************************
     89  SystemStatusPQWM1
     90 ******************************************************************************/
     91 class SystemStatusPQWM1
     92 {
     93 public:
     94     uint16_t mGpsWeek;    // x1
     95     uint32_t mGpsTowMs;   // x2
     96     uint8_t  mTimeValid;  // x3
     97     uint8_t  mTimeSource; // x4
     98     int32_t  mTimeUnc;    // x5
     99     int32_t  mClockFreqBias; // x6
    100     int32_t  mClockFreqBiasUnc; // x7
    101     uint8_t  mXoState;    // x8
    102     int32_t  mPgaGain;    // x9
    103     uint32_t mGpsBpAmpI;  // xA
    104     uint32_t mGpsBpAmpQ;  // xB
    105     uint32_t mAdcI;       // xC
    106     uint32_t mAdcQ;       // xD
    107     uint32_t mJammerGps;  // xE
    108     uint32_t mJammerGlo;  // xF
    109     uint32_t mJammerBds;  // x10
    110     uint32_t mJammerGal;  // x11
    111     uint32_t mRecErrorRecovery; // x12
    112     double   mAgcGps;     // x13
    113     double   mAgcGlo;     // x14
    114     double   mAgcBds;     // x15
    115     double   mAgcGal;     // x16
    116     int32_t  mLeapSeconds;// x17
    117     int32_t  mLeapSecUnc; // x18
    118 };
    119 
    120 // parser
    121 class SystemStatusPQWM1parser : public SystemStatusNmeaBase
    122 {
    123 private:
    124     enum
    125     {
    126         eTalker = 0,
    127         eGpsWeek = 1,
    128         eGpsTowMs = 2,
    129         eTimeValid = 3,
    130         eTimeSource = 4,
    131         eTimeUnc = 5,
    132         eClockFreqBias = 6,
    133         eClockFreqBiasUnc = 7,
    134         eXoState = 8,
    135         ePgaGain = 9,
    136         eGpsBpAmpI = 10,
    137         eGpsBpAmpQ = 11,
    138         eAdcI = 12,
    139         eAdcQ = 13,
    140         eJammerGps = 14,
    141         eJammerGlo = 15,
    142         eJammerBds = 16,
    143         eJammerGal = 17,
    144         eRecErrorRecovery = 18,
    145         eAgcGps = 19,
    146         eAgcGlo = 20,
    147         eAgcBds = 21,
    148         eAgcGal = 22,
    149         eLeapSeconds = 23,
    150         eLeapSecUnc = 24,
    151         eMax
    152     };
    153     SystemStatusPQWM1 mM1;
    154 
    155 public:
    156     inline uint16_t   getGpsWeek()    { return mM1.mGpsWeek; }
    157     inline uint32_t   getGpsTowMs()   { return mM1.mGpsTowMs; }
    158     inline uint8_t    getTimeValid()  { return mM1.mTimeValid; }
    159     inline uint8_t    getTimeSource() { return mM1.mTimeSource; }
    160     inline int32_t    getTimeUnc()    { return mM1.mTimeUnc; }
    161     inline int32_t    getClockFreqBias() { return mM1.mClockFreqBias; }
    162     inline int32_t    getClockFreqBiasUnc() { return mM1.mClockFreqBiasUnc; }
    163     inline uint8_t    getXoState()    { return mM1.mXoState;}
    164     inline int32_t    getPgaGain()    { return mM1.mPgaGain;          }
    165     inline uint32_t   getGpsBpAmpI()  { return mM1.mGpsBpAmpI;        }
    166     inline uint32_t   getGpsBpAmpQ()  { return mM1.mGpsBpAmpQ;        }
    167     inline uint32_t   getAdcI()       { return mM1.mAdcI;             }
    168     inline uint32_t   getAdcQ()       { return mM1.mAdcQ;             }
    169     inline uint32_t   getJammerGps()  { return mM1.mJammerGps;        }
    170     inline uint32_t   getJammerGlo()  { return mM1.mJammerGlo;        }
    171     inline uint32_t   getJammerBds()  { return mM1.mJammerBds;        }
    172     inline uint32_t   getJammerGal()  { return mM1.mJammerGal;        }
    173     inline uint32_t   getAgcGps()     { return mM1.mAgcGps;           }
    174     inline uint32_t   getAgcGlo()     { return mM1.mAgcGlo;           }
    175     inline uint32_t   getAgcBds()     { return mM1.mAgcBds;           }
    176     inline uint32_t   getAgcGal()     { return mM1.mAgcGal;           }
    177     inline uint32_t   getRecErrorRecovery() { return mM1.mRecErrorRecovery; }
    178     inline int32_t    getLeapSeconds(){ return mM1.mLeapSeconds; }
    179     inline int32_t    getLeapSecUnc() { return mM1.mLeapSecUnc; }
    180 
    181     SystemStatusPQWM1parser(const char *str_in, uint32_t len_in)
    182         : SystemStatusNmeaBase(str_in, len_in)
    183     {
    184         memset(&mM1, 0, sizeof(mM1));
    185         if (mField.size() < eMax) {
    186             LOC_LOGE("PQWM1parser - invalid size=%d", mField.size());
    187             mM1.mTimeValid = 0;
    188             return;
    189         }
    190         mM1.mGpsWeek = atoi(mField[eGpsWeek].c_str());
    191         mM1.mGpsTowMs = atoi(mField[eGpsTowMs].c_str());
    192         mM1.mTimeValid = atoi(mField[eTimeValid].c_str());
    193         mM1.mTimeSource = atoi(mField[eTimeSource].c_str());
    194         mM1.mTimeUnc = atoi(mField[eTimeUnc].c_str());
    195         mM1.mClockFreqBias = atoi(mField[eClockFreqBias].c_str());
    196         mM1.mClockFreqBiasUnc = atoi(mField[eClockFreqBiasUnc].c_str());
    197         mM1.mXoState = atoi(mField[eXoState].c_str());
    198         mM1.mPgaGain = atoi(mField[ePgaGain].c_str());
    199         mM1.mGpsBpAmpI = atoi(mField[eGpsBpAmpI].c_str());
    200         mM1.mGpsBpAmpQ = atoi(mField[eGpsBpAmpQ].c_str());
    201         mM1.mAdcI = atoi(mField[eAdcI].c_str());
    202         mM1.mAdcQ = atoi(mField[eAdcQ].c_str());
    203         mM1.mJammerGps = atoi(mField[eJammerGps].c_str());
    204         mM1.mJammerGlo = atoi(mField[eJammerGlo].c_str());
    205         mM1.mJammerBds = atoi(mField[eJammerBds].c_str());
    206         mM1.mJammerGal = atoi(mField[eJammerGal].c_str());
    207         mM1.mRecErrorRecovery = atoi(mField[eRecErrorRecovery].c_str());
    208         mM1.mAgcGps = atof(mField[eAgcGps].c_str());
    209         mM1.mAgcGlo = atof(mField[eAgcGlo].c_str());
    210         mM1.mAgcBds = atof(mField[eAgcBds].c_str());
    211         mM1.mAgcGal = atof(mField[eAgcGal].c_str());
    212         mM1.mLeapSeconds = atoi(mField[eLeapSeconds].c_str());
    213         mM1.mLeapSecUnc = atoi(mField[eLeapSecUnc].c_str());
    214     }
    215 
    216     inline SystemStatusPQWM1& get() { return mM1;} //getparser
    217 };
    218 
    219 /******************************************************************************
    220  SystemStatusPQWP1
    221 ******************************************************************************/
    222 class SystemStatusPQWP1
    223 {
    224 public:
    225     uint8_t  mEpiValidity; // x4
    226     float    mEpiLat;    // x5
    227     float    mEpiLon;    // x6
    228     float    mEpiAlt;    // x7
    229     float    mEpiHepe;   // x8
    230     float    mEpiAltUnc; // x9
    231     uint8_t  mEpiSrc;    // x10
    232 };
    233 
    234 class SystemStatusPQWP1parser : public SystemStatusNmeaBase
    235 {
    236 private:
    237     enum
    238     {
    239         eTalker = 0,
    240         eUtcTime = 1,
    241         eEpiValidity = 2,
    242         eEpiLat = 3,
    243         eEpiLon = 4,
    244         eEpiAlt = 5,
    245         eEpiHepe = 6,
    246         eEpiAltUnc = 7,
    247         eEpiSrc = 8,
    248         eMax
    249     };
    250     SystemStatusPQWP1 mP1;
    251 
    252 public:
    253     inline uint8_t    getEpiValidity() { return mP1.mEpiValidity;      }
    254     inline float      getEpiLat() { return mP1.mEpiLat;           }
    255     inline float      getEpiLon() { return mP1.mEpiLon;           }
    256     inline float      getEpiAlt() { return mP1.mEpiAlt;           }
    257     inline float      getEpiHepe() { return mP1.mEpiHepe;          }
    258     inline float      getEpiAltUnc() { return mP1.mEpiAltUnc;        }
    259     inline uint8_t    getEpiSrc() { return mP1.mEpiSrc;           }
    260 
    261     SystemStatusPQWP1parser(const char *str_in, uint32_t len_in)
    262         : SystemStatusNmeaBase(str_in, len_in)
    263     {
    264         if (mField.size() < eMax) {
    265             return;
    266         }
    267         memset(&mP1, 0, sizeof(mP1));
    268         mP1.mEpiValidity = strtol(mField[eEpiValidity].c_str(), NULL, 16);
    269         mP1.mEpiLat = atof(mField[eEpiLat].c_str());
    270         mP1.mEpiLon = atof(mField[eEpiLon].c_str());
    271         mP1.mEpiAlt = atof(mField[eEpiAlt].c_str());
    272         mP1.mEpiHepe = atoi(mField[eEpiHepe].c_str());
    273         mP1.mEpiAltUnc = atof(mField[eEpiAltUnc].c_str());
    274         mP1.mEpiSrc = atoi(mField[eEpiSrc].c_str());
    275     }
    276 
    277     inline SystemStatusPQWP1& get() { return mP1;}
    278 };
    279 
    280 /******************************************************************************
    281  SystemStatusPQWP2
    282 ******************************************************************************/
    283 class SystemStatusPQWP2
    284 {
    285 public:
    286     float    mBestLat;   // x4
    287     float    mBestLon;   // x5
    288     float    mBestAlt;   // x6
    289     float    mBestHepe;  // x7
    290     float    mBestAltUnc; // x8
    291 };
    292 
    293 class SystemStatusPQWP2parser : public SystemStatusNmeaBase
    294 {
    295 private:
    296     enum
    297     {
    298         eTalker = 0,
    299         eUtcTime = 1,
    300         eBestLat = 2,
    301         eBestLon = 3,
    302         eBestAlt = 4,
    303         eBestHepe = 5,
    304         eBestAltUnc = 6,
    305         eMax
    306     };
    307     SystemStatusPQWP2 mP2;
    308 
    309 public:
    310     inline float      getBestLat() { return mP2.mBestLat;          }
    311     inline float      getBestLon() { return mP2.mBestLon;          }
    312     inline float      getBestAlt() { return mP2.mBestAlt;          }
    313     inline float      getBestHepe() { return mP2.mBestHepe;         }
    314     inline float      getBestAltUnc() { return mP2.mBestAltUnc;       }
    315 
    316     SystemStatusPQWP2parser(const char *str_in, uint32_t len_in)
    317         : SystemStatusNmeaBase(str_in, len_in)
    318     {
    319         if (mField.size() < eMax) {
    320             return;
    321         }
    322         memset(&mP2, 0, sizeof(mP2));
    323         mP2.mBestLat = atof(mField[eBestLat].c_str());
    324         mP2.mBestLon = atof(mField[eBestLon].c_str());
    325         mP2.mBestAlt = atof(mField[eBestAlt].c_str());
    326         mP2.mBestHepe = atof(mField[eBestHepe].c_str());
    327         mP2.mBestAltUnc = atof(mField[eBestAltUnc].c_str());
    328     }
    329 
    330     inline SystemStatusPQWP2& get() { return mP2;}
    331 };
    332 
    333 /******************************************************************************
    334  SystemStatusPQWP3
    335 ******************************************************************************/
    336 class SystemStatusPQWP3
    337 {
    338 public:
    339     uint8_t   mXtraValidMask;
    340     uint32_t  mGpsXtraAge;
    341     uint32_t  mGloXtraAge;
    342     uint32_t  mBdsXtraAge;
    343     uint32_t  mGalXtraAge;
    344     uint32_t  mQzssXtraAge;
    345     uint32_t  mGpsXtraValid;
    346     uint32_t  mGloXtraValid;
    347     uint64_t  mBdsXtraValid;
    348     uint64_t  mGalXtraValid;
    349     uint8_t   mQzssXtraValid;
    350 };
    351 
    352 class SystemStatusPQWP3parser : public SystemStatusNmeaBase
    353 {
    354 private:
    355     enum
    356     {
    357         eTalker = 0,
    358         eUtcTime = 1,
    359         eXtraValidMask = 2,
    360         eGpsXtraAge = 3,
    361         eGloXtraAge = 4,
    362         eBdsXtraAge = 5,
    363         eGalXtraAge = 6,
    364         eQzssXtraAge = 7,
    365         eGpsXtraValid = 8,
    366         eGloXtraValid = 9,
    367         eBdsXtraValid = 10,
    368         eGalXtraValid = 11,
    369         eQzssXtraValid = 12,
    370         eMax
    371     };
    372     SystemStatusPQWP3 mP3;
    373 
    374 public:
    375     inline uint8_t    getXtraValid() { return mP3.mXtraValidMask;   }
    376     inline uint32_t   getGpsXtraAge() { return mP3.mGpsXtraAge;       }
    377     inline uint32_t   getGloXtraAge() { return mP3.mGloXtraAge;       }
    378     inline uint32_t   getBdsXtraAge() { return mP3.mBdsXtraAge;       }
    379     inline uint32_t   getGalXtraAge() { return mP3.mGalXtraAge;       }
    380     inline uint32_t   getQzssXtraAge() { return mP3.mQzssXtraAge;      }
    381     inline uint32_t   getGpsXtraValid() { return mP3.mGpsXtraValid;     }
    382     inline uint32_t   getGloXtraValid() { return mP3.mGloXtraValid;     }
    383     inline uint64_t   getBdsXtraValid() { return mP3.mBdsXtraValid;     }
    384     inline uint64_t   getGalXtraValid() { return mP3.mGalXtraValid;     }
    385     inline uint8_t    getQzssXtraValid() { return mP3.mQzssXtraValid;    }
    386 
    387     SystemStatusPQWP3parser(const char *str_in, uint32_t len_in)
    388         : SystemStatusNmeaBase(str_in, len_in)
    389     {
    390         if (mField.size() < eMax) {
    391             return;
    392         }
    393         memset(&mP3, 0, sizeof(mP3));
    394         mP3.mXtraValidMask = strtol(mField[eXtraValidMask].c_str(), NULL, 16);
    395         mP3.mGpsXtraAge = atoi(mField[eGpsXtraAge].c_str());
    396         mP3.mGloXtraAge = atoi(mField[eGloXtraAge].c_str());
    397         mP3.mBdsXtraAge = atoi(mField[eBdsXtraAge].c_str());
    398         mP3.mGalXtraAge = atoi(mField[eGalXtraAge].c_str());
    399         mP3.mQzssXtraAge = atoi(mField[eQzssXtraAge].c_str());
    400         mP3.mGpsXtraValid = strtol(mField[eGpsXtraValid].c_str(), NULL, 16);
    401         mP3.mGloXtraValid = strtol(mField[eGloXtraValid].c_str(), NULL, 16);
    402         mP3.mBdsXtraValid = strtol(mField[eBdsXtraValid].c_str(), NULL, 16);
    403         mP3.mGalXtraValid = strtol(mField[eGalXtraValid].c_str(), NULL, 16);
    404         mP3.mQzssXtraValid = strtol(mField[eQzssXtraValid].c_str(), NULL, 16);
    405     }
    406 
    407     inline SystemStatusPQWP3& get() { return mP3;}
    408 };
    409 
    410 /******************************************************************************
    411  SystemStatusPQWP4
    412 ******************************************************************************/
    413 class SystemStatusPQWP4
    414 {
    415 public:
    416     uint32_t  mGpsEpheValid;
    417     uint32_t  mGloEpheValid;
    418     uint64_t  mBdsEpheValid;
    419     uint64_t  mGalEpheValid;
    420     uint8_t   mQzssEpheValid;
    421 };
    422 
    423 class SystemStatusPQWP4parser : public SystemStatusNmeaBase
    424 {
    425 private:
    426     enum
    427     {
    428         eTalker = 0,
    429         eUtcTime = 1,
    430         eGpsEpheValid = 2,
    431         eGloEpheValid = 3,
    432         eBdsEpheValid = 4,
    433         eGalEpheValid = 5,
    434         eQzssEpheValid = 6,
    435         eMax
    436     };
    437     SystemStatusPQWP4 mP4;
    438 
    439 public:
    440     inline uint32_t   getGpsEpheValid() { return mP4.mGpsEpheValid;     }
    441     inline uint32_t   getGloEpheValid() { return mP4.mGloEpheValid;     }
    442     inline uint64_t   getBdsEpheValid() { return mP4.mBdsEpheValid;     }
    443     inline uint64_t   getGalEpheValid() { return mP4.mGalEpheValid;     }
    444     inline uint8_t    getQzssEpheValid() { return mP4.mQzssEpheValid;    }
    445 
    446     SystemStatusPQWP4parser(const char *str_in, uint32_t len_in)
    447         : SystemStatusNmeaBase(str_in, len_in)
    448     {
    449         if (mField.size() < eMax) {
    450             return;
    451         }
    452         memset(&mP4, 0, sizeof(mP4));
    453         mP4.mGpsEpheValid = strtol(mField[eGpsEpheValid].c_str(), NULL, 16);
    454         mP4.mGloEpheValid = strtol(mField[eGloEpheValid].c_str(), NULL, 16);
    455         mP4.mBdsEpheValid = strtol(mField[eBdsEpheValid].c_str(), NULL, 16);
    456         mP4.mGalEpheValid = strtol(mField[eGalEpheValid].c_str(), NULL, 16);
    457         mP4.mQzssEpheValid = strtol(mField[eQzssEpheValid].c_str(), NULL, 16);
    458     }
    459 
    460     inline SystemStatusPQWP4& get() { return mP4;}
    461 };
    462 
    463 /******************************************************************************
    464  SystemStatusPQWP5
    465 ******************************************************************************/
    466 class SystemStatusPQWP5
    467 {
    468 public:
    469     uint32_t  mGpsUnknownMask;
    470     uint32_t  mGloUnknownMask;
    471     uint64_t  mBdsUnknownMask;
    472     uint64_t  mGalUnknownMask;
    473     uint8_t   mQzssUnknownMask;
    474     uint32_t  mGpsGoodMask;
    475     uint32_t  mGloGoodMask;
    476     uint64_t  mBdsGoodMask;
    477     uint64_t  mGalGoodMask;
    478     uint8_t   mQzssGoodMask;
    479     uint32_t  mGpsBadMask;
    480     uint32_t  mGloBadMask;
    481     uint64_t  mBdsBadMask;
    482     uint64_t  mGalBadMask;
    483     uint8_t   mQzssBadMask;
    484 };
    485 
    486 class SystemStatusPQWP5parser : public SystemStatusNmeaBase
    487 {
    488 private:
    489     enum
    490     {
    491         eTalker = 0,
    492         eUtcTime = 1,
    493         eGpsUnknownMask = 2,
    494         eGloUnknownMask = 3,
    495         eBdsUnknownMask = 4,
    496         eGalUnknownMask = 5,
    497         eQzssUnknownMask = 6,
    498         eGpsGoodMask = 7,
    499         eGloGoodMask = 8,
    500         eBdsGoodMask = 9,
    501         eGalGoodMask = 10,
    502         eQzssGoodMask = 11,
    503         eGpsBadMask = 12,
    504         eGloBadMask = 13,
    505         eBdsBadMask = 14,
    506         eGalBadMask = 15,
    507         eQzssBadMask = 16,
    508         eMax
    509     };
    510     SystemStatusPQWP5 mP5;
    511 
    512 public:
    513     inline uint32_t   getGpsUnknownMask() { return mP5.mGpsUnknownMask;   }
    514     inline uint32_t   getGloUnknownMask() { return mP5.mGloUnknownMask;   }
    515     inline uint64_t   getBdsUnknownMask() { return mP5.mBdsUnknownMask;   }
    516     inline uint64_t   getGalUnknownMask() { return mP5.mGalUnknownMask;   }
    517     inline uint8_t    getQzssUnknownMask() { return mP5.mQzssUnknownMask;  }
    518     inline uint32_t   getGpsGoodMask() { return mP5.mGpsGoodMask;      }
    519     inline uint32_t   getGloGoodMask() { return mP5.mGloGoodMask;      }
    520     inline uint64_t   getBdsGoodMask() { return mP5.mBdsGoodMask;      }
    521     inline uint64_t   getGalGoodMask() { return mP5.mGalGoodMask;      }
    522     inline uint8_t    getQzssGoodMask() { return mP5.mQzssGoodMask;     }
    523     inline uint32_t   getGpsBadMask() { return mP5.mGpsBadMask;       }
    524     inline uint32_t   getGloBadMask() { return mP5.mGloBadMask;       }
    525     inline uint64_t   getBdsBadMask() { return mP5.mBdsBadMask;       }
    526     inline uint64_t   getGalBadMask() { return mP5.mGalBadMask;       }
    527     inline uint8_t    getQzssBadMask() { return mP5.mQzssBadMask;      }
    528 
    529     SystemStatusPQWP5parser(const char *str_in, uint32_t len_in)
    530         : SystemStatusNmeaBase(str_in, len_in)
    531     {
    532         if (mField.size() < eMax) {
    533             return;
    534         }
    535         memset(&mP5, 0, sizeof(mP5));
    536         mP5.mGpsUnknownMask = strtol(mField[eGpsUnknownMask].c_str(), NULL, 16);
    537         mP5.mGloUnknownMask = strtol(mField[eGloUnknownMask].c_str(), NULL, 16);
    538         mP5.mBdsUnknownMask = strtol(mField[eBdsUnknownMask].c_str(), NULL, 16);
    539         mP5.mGalUnknownMask = strtol(mField[eGalUnknownMask].c_str(), NULL, 16);
    540         mP5.mQzssUnknownMask = strtol(mField[eQzssUnknownMask].c_str(), NULL, 16);
    541         mP5.mGpsGoodMask = strtol(mField[eGpsGoodMask].c_str(), NULL, 16);
    542         mP5.mGloGoodMask = strtol(mField[eGloGoodMask].c_str(), NULL, 16);
    543         mP5.mBdsGoodMask = strtol(mField[eBdsGoodMask].c_str(), NULL, 16);
    544         mP5.mGalGoodMask = strtol(mField[eGalGoodMask].c_str(), NULL, 16);
    545         mP5.mQzssGoodMask = strtol(mField[eQzssGoodMask].c_str(), NULL, 16);
    546         mP5.mGpsBadMask = strtol(mField[eGpsBadMask].c_str(), NULL, 16);
    547         mP5.mGloBadMask = strtol(mField[eGloBadMask].c_str(), NULL, 16);
    548         mP5.mBdsBadMask = strtol(mField[eBdsBadMask].c_str(), NULL, 16);
    549         mP5.mGalBadMask = strtol(mField[eGalBadMask].c_str(), NULL, 16);
    550         mP5.mQzssBadMask = strtol(mField[eQzssBadMask].c_str(), NULL, 16);
    551     }
    552 
    553     inline SystemStatusPQWP5& get() { return mP5;}
    554 };
    555 
    556 /******************************************************************************
    557  SystemStatusPQWP6parser
    558 ******************************************************************************/
    559 class SystemStatusPQWP6
    560 {
    561 public:
    562     uint32_t  mFixInfoMask;
    563 };
    564 
    565 class SystemStatusPQWP6parser : public SystemStatusNmeaBase
    566 {
    567 private:
    568     enum
    569     {
    570         eTalker = 0,
    571         eUtcTime = 1,
    572         eFixInfoMask = 2,
    573         eMax
    574     };
    575     SystemStatusPQWP6 mP6;
    576 
    577 public:
    578     inline uint32_t   getFixInfoMask() { return mP6.mFixInfoMask;      }
    579 
    580     SystemStatusPQWP6parser(const char *str_in, uint32_t len_in)
    581         : SystemStatusNmeaBase(str_in, len_in)
    582     {
    583         if (mField.size() < eMax) {
    584             return;
    585         }
    586         memset(&mP6, 0, sizeof(mP6));
    587         mP6.mFixInfoMask = strtol(mField[eFixInfoMask].c_str(), NULL, 16);
    588     }
    589 
    590     inline SystemStatusPQWP6& get() { return mP6;}
    591 };
    592 
    593 /******************************************************************************
    594  SystemStatusPQWP7parser
    595 ******************************************************************************/
    596 class SystemStatusPQWP7
    597 {
    598 public:
    599     SystemStatusNav mNav[SV_ALL_NUM];
    600 };
    601 
    602 class SystemStatusPQWP7parser : public SystemStatusNmeaBase
    603 {
    604 private:
    605     enum
    606     {
    607         eTalker = 0,
    608         eUtcTime = 1,
    609         eMax = 2 + SV_ALL_NUM*3
    610     };
    611     SystemStatusPQWP7 mP7;
    612 
    613 public:
    614     SystemStatusPQWP7parser(const char *str_in, uint32_t len_in)
    615         : SystemStatusNmeaBase(str_in, len_in)
    616     {
    617         if (mField.size() < eMax) {
    618             LOC_LOGE("PQWP7parser - invalid size=%d", mField.size());
    619             return;
    620         }
    621         for (uint32_t i=0; i<SV_ALL_NUM; i++) {
    622             mP7.mNav[i].mType   = GnssEphemerisType(atoi(mField[i*3+2].c_str()));
    623             mP7.mNav[i].mSource = GnssEphemerisSource(atoi(mField[i*3+3].c_str()));
    624             mP7.mNav[i].mAgeSec = atoi(mField[i*3+4].c_str());
    625         }
    626     }
    627 
    628     inline SystemStatusPQWP7& get() { return mP7;}
    629 };
    630 
    631 /******************************************************************************
    632  SystemStatusPQWS1parser
    633 ******************************************************************************/
    634 class SystemStatusPQWS1
    635 {
    636 public:
    637     uint32_t  mFixInfoMask;
    638     uint32_t  mHepeLimit;
    639 };
    640 
    641 class SystemStatusPQWS1parser : public SystemStatusNmeaBase
    642 {
    643 private:
    644     enum
    645     {
    646         eTalker = 0,
    647         eUtcTime = 1,
    648         eFixInfoMask = 2,
    649         eHepeLimit = 3,
    650         eMax
    651     };
    652     SystemStatusPQWS1 mS1;
    653 
    654 public:
    655     inline uint16_t   getFixInfoMask() { return mS1.mFixInfoMask;      }
    656     inline uint32_t   getHepeLimit()   { return mS1.mHepeLimit;      }
    657 
    658     SystemStatusPQWS1parser(const char *str_in, uint32_t len_in)
    659         : SystemStatusNmeaBase(str_in, len_in)
    660     {
    661         if (mField.size() < eMax) {
    662             return;
    663         }
    664         memset(&mS1, 0, sizeof(mS1));
    665         mS1.mFixInfoMask = atoi(mField[eFixInfoMask].c_str());
    666         mS1.mHepeLimit = atoi(mField[eHepeLimit].c_str());
    667     }
    668 
    669     inline SystemStatusPQWS1& get() { return mS1;}
    670 };
    671 
    672 /******************************************************************************
    673  SystemStatusTimeAndClock
    674 ******************************************************************************/
    675 SystemStatusTimeAndClock::SystemStatusTimeAndClock(const SystemStatusPQWM1& nmea) :
    676     mGpsWeek(nmea.mGpsWeek),
    677     mGpsTowMs(nmea.mGpsTowMs),
    678     mTimeValid(nmea.mTimeValid),
    679     mTimeSource(nmea.mTimeSource),
    680     mTimeUnc(nmea.mTimeUnc),
    681     mClockFreqBias(nmea.mClockFreqBias),
    682     mClockFreqBiasUnc(nmea.mClockFreqBiasUnc),
    683     mLeapSeconds(nmea.mLeapSeconds),
    684     mLeapSecUnc(nmea.mLeapSecUnc)
    685 {
    686 }
    687 
    688 bool SystemStatusTimeAndClock::equals(SystemStatusTimeAndClock& peer)
    689 {
    690     if ((mGpsWeek != peer.mGpsWeek) ||
    691         (mGpsTowMs != peer.mGpsTowMs) ||
    692         (mTimeValid != peer.mTimeValid) ||
    693         (mTimeSource != peer.mTimeSource) ||
    694         (mTimeUnc != peer.mTimeUnc) ||
    695         (mClockFreqBias != peer.mClockFreqBias) ||
    696         (mClockFreqBiasUnc != peer.mClockFreqBiasUnc) ||
    697         (mLeapSeconds != peer.mLeapSeconds) ||
    698         (mLeapSecUnc != peer.mLeapSecUnc)) {
    699         return false;
    700     }
    701     return true;
    702 }
    703 
    704 void SystemStatusTimeAndClock::dump()
    705 {
    706     LOC_LOGV("TimeAndClock: u=%ld:%ld g=%d:%d v=%d ts=%d tu=%d b=%d bu=%d ls=%d lu=%d",
    707              mUtcTime.tv_sec, mUtcTime.tv_nsec,
    708              mGpsWeek,
    709              mGpsTowMs,
    710              mTimeValid,
    711              mTimeSource,
    712              mTimeUnc,
    713              mClockFreqBias,
    714              mClockFreqBiasUnc,
    715              mLeapSeconds,
    716              mLeapSecUnc);
    717     return;
    718 }
    719 
    720 /******************************************************************************
    721  SystemStatusXoState
    722 ******************************************************************************/
    723 SystemStatusXoState::SystemStatusXoState(const SystemStatusPQWM1& nmea) :
    724     mXoState(nmea.mXoState)
    725 {
    726 }
    727 
    728 bool SystemStatusXoState::equals(SystemStatusXoState& peer)
    729 {
    730     if (mXoState != peer.mXoState) {
    731         return false;
    732     }
    733     return true;
    734 }
    735 
    736 void SystemStatusXoState::dump()
    737 {
    738     LOC_LOGV("XoState: u=%ld:%ld x=%d",
    739              mUtcTime.tv_sec, mUtcTime.tv_nsec,
    740              mXoState);
    741     return;
    742 }
    743 
    744 /******************************************************************************
    745  SystemStatusRfAndParams
    746 ******************************************************************************/
    747 SystemStatusRfAndParams::SystemStatusRfAndParams(const SystemStatusPQWM1& nmea) :
    748     mPgaGain(nmea.mPgaGain),
    749     mGpsBpAmpI(nmea.mGpsBpAmpI),
    750     mGpsBpAmpQ(nmea.mGpsBpAmpQ),
    751     mAdcI(nmea.mAdcI),
    752     mAdcQ(nmea.mAdcQ),
    753     mJammerGps(nmea.mJammerGps),
    754     mJammerGlo(nmea.mJammerGlo),
    755     mJammerBds(nmea.mJammerBds),
    756     mJammerGal(nmea.mJammerGal),
    757     mAgcGps(nmea.mAgcGps),
    758     mAgcGlo(nmea.mAgcGlo),
    759     mAgcBds(nmea.mAgcBds),
    760     mAgcGal(nmea.mAgcGal)
    761 {
    762 }
    763 
    764 bool SystemStatusRfAndParams::equals(SystemStatusRfAndParams& peer)
    765 {
    766     if ((mPgaGain != peer.mPgaGain) ||
    767         (mGpsBpAmpI != peer.mGpsBpAmpI) ||
    768         (mGpsBpAmpQ != peer.mGpsBpAmpQ) ||
    769         (mAdcI != peer.mAdcI) ||
    770         (mAdcQ != peer.mAdcQ) ||
    771         (mJammerGps != peer.mJammerGps) ||
    772         (mJammerGlo != peer.mJammerGlo) ||
    773         (mJammerBds != peer.mJammerBds) ||
    774         (mJammerGal != peer.mJammerGal) ||
    775         (mAgcGps != peer.mAgcGps) ||
    776         (mAgcGlo != peer.mAgcGlo) ||
    777         (mAgcBds != peer.mAgcBds) ||
    778         (mAgcGal != peer.mAgcGal)) {
    779         return false;
    780     }
    781     return true;
    782 }
    783 
    784 void SystemStatusRfAndParams::dump()
    785 {
    786     LOC_LOGV("RfAndParams: u=%ld:%ld p=%d bi=%d bq=%d ai=%d aq=%d "
    787              "jgp=%d jgl=%d jbd=%d jga=%d "
    788              "agp=%lf agl=%lf abd=%lf aga=%lf",
    789              mUtcTime.tv_sec, mUtcTime.tv_nsec,
    790              mPgaGain,
    791              mGpsBpAmpI,
    792              mGpsBpAmpQ,
    793              mAdcI,
    794              mAdcQ,
    795              mJammerGps,
    796              mJammerGlo,
    797              mJammerBds,
    798              mJammerGal,
    799              mAgcGps,
    800              mAgcGlo,
    801              mAgcBds,
    802              mAgcGal);
    803     return;
    804 }
    805 
    806 /******************************************************************************
    807  SystemStatusErrRecovery
    808 ******************************************************************************/
    809 SystemStatusErrRecovery::SystemStatusErrRecovery(const SystemStatusPQWM1& nmea) :
    810     mRecErrorRecovery(nmea.mRecErrorRecovery)
    811 {
    812 }
    813 
    814 bool SystemStatusErrRecovery::equals(SystemStatusErrRecovery& peer)
    815 {
    816     if (mRecErrorRecovery != peer.mRecErrorRecovery) {
    817         return false;
    818     }
    819     return true;
    820 }
    821 
    822 void SystemStatusErrRecovery::dump()
    823 {
    824     LOC_LOGV("ErrRecovery: u=%ld:%ld e=%d",
    825              mUtcTime.tv_sec, mUtcTime.tv_nsec,
    826              mRecErrorRecovery);
    827     return;
    828 }
    829 
    830 /******************************************************************************
    831  SystemStatusInjectedPosition
    832 ******************************************************************************/
    833 SystemStatusInjectedPosition::SystemStatusInjectedPosition(const SystemStatusPQWP1& nmea) :
    834     mEpiValidity(nmea.mEpiValidity),
    835     mEpiLat(nmea.mEpiLat),
    836     mEpiLon(nmea.mEpiLon),
    837     mEpiAlt(nmea.mEpiAlt),
    838     mEpiHepe(nmea.mEpiHepe),
    839     mEpiAltUnc(nmea.mEpiAltUnc),
    840     mEpiSrc(nmea.mEpiSrc)
    841 {
    842 }
    843 
    844 bool SystemStatusInjectedPosition::equals(SystemStatusInjectedPosition& peer)
    845 {
    846     if ((mEpiValidity != peer.mEpiValidity) ||
    847         (mEpiLat != peer.mEpiLat) ||
    848         (mEpiLon != peer.mEpiLon) ||
    849         (mEpiAlt != peer.mEpiAlt) ||
    850         (mEpiHepe != peer.mEpiHepe) ||
    851         (mEpiAltUnc != peer.mEpiAltUnc) ||
    852         (mEpiSrc != peer.mEpiSrc)) {
    853         return false;
    854     }
    855     return true;
    856 }
    857 
    858 void SystemStatusInjectedPosition::dump()
    859 {
    860     LOC_LOGV("InjectedPosition: u=%ld:%ld v=%x la=%f lo=%f al=%f he=%f au=%f es=%d",
    861              mUtcTime.tv_sec, mUtcTime.tv_nsec,
    862              mEpiValidity,
    863              mEpiLat,
    864              mEpiLon,
    865              mEpiAlt,
    866              mEpiHepe,
    867              mEpiAltUnc,
    868              mEpiSrc);
    869     return;
    870 }
    871 
    872 /******************************************************************************
    873  SystemStatusBestPosition
    874 ******************************************************************************/
    875 SystemStatusBestPosition::SystemStatusBestPosition(const SystemStatusPQWP2& nmea) :
    876     mValid(true),
    877     mBestLat(nmea.mBestLat),
    878     mBestLon(nmea.mBestLon),
    879     mBestAlt(nmea.mBestAlt),
    880     mBestHepe(nmea.mBestHepe),
    881     mBestAltUnc(nmea.mBestAltUnc)
    882 {
    883 }
    884 
    885 bool SystemStatusBestPosition::equals(SystemStatusBestPosition& peer)
    886 {
    887     if ((mBestLat != peer.mBestLat) ||
    888         (mBestLon != peer.mBestLon) ||
    889         (mBestAlt != peer.mBestAlt) ||
    890         (mBestHepe != peer.mBestHepe) ||
    891         (mBestAltUnc != peer.mBestAltUnc)) {
    892         return false;
    893     }
    894     return true;
    895 }
    896 
    897 void SystemStatusBestPosition::dump()
    898 {
    899     LOC_LOGV("BestPosition: u=%ld:%ld la=%f lo=%f al=%f he=%f au=%f",
    900              mUtcTime.tv_sec, mUtcTime.tv_nsec,
    901              mBestLat,
    902              mBestLon,
    903              mBestAlt,
    904              mBestHepe,
    905              mBestAltUnc);
    906     return;
    907 }
    908 
    909 /******************************************************************************
    910  SystemStatusXtra
    911 ******************************************************************************/
    912 SystemStatusXtra::SystemStatusXtra(const SystemStatusPQWP3& nmea) :
    913     mXtraValidMask(nmea.mXtraValidMask),
    914     mGpsXtraAge(nmea.mGpsXtraAge),
    915     mGloXtraAge(nmea.mGloXtraAge),
    916     mBdsXtraAge(nmea.mBdsXtraAge),
    917     mGalXtraAge(nmea.mGalXtraAge),
    918     mQzssXtraAge(nmea.mQzssXtraAge),
    919     mGpsXtraValid(nmea.mGpsXtraValid),
    920     mGloXtraValid(nmea.mGloXtraValid),
    921     mBdsXtraValid(nmea.mBdsXtraValid),
    922     mGalXtraValid(nmea.mGalXtraValid),
    923     mQzssXtraValid(nmea.mQzssXtraValid)
    924 {
    925 }
    926 
    927 bool SystemStatusXtra::equals(SystemStatusXtra& peer)
    928 {
    929     if ((mXtraValidMask != peer.mXtraValidMask) ||
    930         (mGpsXtraAge != peer.mGpsXtraAge) ||
    931         (mGloXtraAge != peer.mGloXtraAge) ||
    932         (mBdsXtraAge != peer.mBdsXtraAge) ||
    933         (mGalXtraAge != peer.mGalXtraAge) ||
    934         (mQzssXtraAge != peer.mQzssXtraAge) ||
    935         (mGpsXtraValid != peer.mGpsXtraValid) ||
    936         (mGloXtraValid != peer.mGloXtraValid) ||
    937         (mBdsXtraValid != peer.mBdsXtraValid) ||
    938         (mGalXtraValid != peer.mGalXtraValid) ||
    939         (mQzssXtraValid != peer.mQzssXtraValid)) {
    940         return false;
    941     }
    942     return true;
    943 }
    944 
    945 void SystemStatusXtra::dump()
    946 {
    947     LOC_LOGV("SystemStatusXtra: u=%ld:%ld m=%x a=%d:%d:%d:%d:%d v=%x:%x:%x:%x:%x",
    948              mUtcTime.tv_sec, mUtcTime.tv_nsec,
    949              mXtraValidMask,
    950              mGpsXtraAge,
    951              mGloXtraAge,
    952              mBdsXtraAge,
    953              mGalXtraAge,
    954              mQzssXtraAge,
    955              mGpsXtraValid,
    956              mGloXtraValid,
    957              mBdsXtraValid,
    958              mGalXtraValid,
    959              mQzssXtraValid);
    960     return;
    961 }
    962 
    963 /******************************************************************************
    964  SystemStatusEphemeris
    965 ******************************************************************************/
    966 SystemStatusEphemeris::SystemStatusEphemeris(const SystemStatusPQWP4& nmea) :
    967     mGpsEpheValid(nmea.mGpsEpheValid),
    968     mGloEpheValid(nmea.mGloEpheValid),
    969     mBdsEpheValid(nmea.mBdsEpheValid),
    970     mGalEpheValid(nmea.mGalEpheValid),
    971     mQzssEpheValid(nmea.mQzssEpheValid)
    972 {
    973 }
    974 
    975 bool SystemStatusEphemeris::equals(SystemStatusEphemeris& peer)
    976 {
    977     if ((mGpsEpheValid != peer.mGpsEpheValid) ||
    978         (mGloEpheValid != peer.mGloEpheValid) ||
    979         (mBdsEpheValid != peer.mBdsEpheValid) ||
    980         (mGalEpheValid != peer.mGalEpheValid) ||
    981         (mQzssEpheValid != peer.mQzssEpheValid)) {
    982         return false;
    983     }
    984     return true;
    985 }
    986 
    987 void SystemStatusEphemeris::dump()
    988 {
    989     LOC_LOGV("Ephemeris: u=%ld:%ld ev=%x:%x:%x:%x:%x",
    990              mUtcTime.tv_sec, mUtcTime.tv_nsec,
    991              mGpsEpheValid,
    992              mGloEpheValid,
    993              mBdsEpheValid,
    994              mGalEpheValid,
    995              mQzssEpheValid);
    996     return;
    997 }
    998 
    999 /******************************************************************************
   1000  SystemStatusSvHealth
   1001 ******************************************************************************/
   1002 SystemStatusSvHealth::SystemStatusSvHealth(const SystemStatusPQWP5& nmea) :
   1003     mGpsUnknownMask(nmea.mGpsUnknownMask),
   1004     mGloUnknownMask(nmea.mGloUnknownMask),
   1005     mBdsUnknownMask(nmea.mBdsUnknownMask),
   1006     mGalUnknownMask(nmea.mGalUnknownMask),
   1007     mQzssUnknownMask(nmea.mQzssUnknownMask),
   1008     mGpsGoodMask(nmea.mGpsGoodMask),
   1009     mGloGoodMask(nmea.mGloGoodMask),
   1010     mBdsGoodMask(nmea.mBdsGoodMask),
   1011     mGalGoodMask(nmea.mGalGoodMask),
   1012     mQzssGoodMask(nmea.mQzssGoodMask),
   1013     mGpsBadMask(nmea.mGpsBadMask),
   1014     mGloBadMask(nmea.mGloBadMask),
   1015     mBdsBadMask(nmea.mBdsBadMask),
   1016     mGalBadMask(nmea.mGalBadMask),
   1017     mQzssBadMask(nmea.mQzssBadMask)
   1018 {
   1019 }
   1020 
   1021 bool SystemStatusSvHealth::equals(SystemStatusSvHealth& peer)
   1022 {
   1023     if ((mGpsUnknownMask != peer.mGpsUnknownMask) ||
   1024         (mGloUnknownMask != peer.mGloUnknownMask) ||
   1025         (mBdsUnknownMask != peer.mBdsUnknownMask) ||
   1026         (mGalUnknownMask != peer.mGalUnknownMask) ||
   1027         (mQzssUnknownMask != peer.mQzssUnknownMask) ||
   1028         (mGpsGoodMask != peer.mGpsGoodMask) ||
   1029         (mGloGoodMask != peer.mGloGoodMask) ||
   1030         (mBdsGoodMask != peer.mBdsGoodMask) ||
   1031         (mGalGoodMask != peer.mGalGoodMask) ||
   1032         (mQzssGoodMask != peer.mQzssGoodMask) ||
   1033         (mGpsBadMask != peer.mGpsBadMask) ||
   1034         (mGloBadMask != peer.mGloBadMask) ||
   1035         (mBdsBadMask != peer.mBdsBadMask) ||
   1036         (mGalBadMask != peer.mGalBadMask) ||
   1037         (mQzssBadMask != peer.mQzssBadMask)) {
   1038         return false;
   1039     }
   1040     return true;
   1041 }
   1042 
   1043 void SystemStatusSvHealth::dump()
   1044 {
   1045     LOC_LOGV("SvHealth: u=%ld:%ld u=%x:%x:%x:%x:%x g=%x:%x:%x:%x:%x b=%x:%x:%x:%x:%x",
   1046              mUtcTime.tv_sec, mUtcTime.tv_nsec,
   1047              mGpsUnknownMask,
   1048              mGloUnknownMask,
   1049              mBdsUnknownMask,
   1050              mGalUnknownMask,
   1051              mQzssUnknownMask,
   1052              mGpsGoodMask,
   1053              mGloGoodMask,
   1054              mBdsGoodMask,
   1055              mGalGoodMask,
   1056              mQzssGoodMask,
   1057              mGpsBadMask,
   1058              mGloBadMask,
   1059              mBdsBadMask,
   1060              mGalBadMask,
   1061              mQzssBadMask);
   1062     return;
   1063 }
   1064 
   1065 /******************************************************************************
   1066  SystemStatusPdr
   1067 ******************************************************************************/
   1068 SystemStatusPdr::SystemStatusPdr(const SystemStatusPQWP6& nmea) :
   1069     mFixInfoMask(nmea.mFixInfoMask)
   1070 {
   1071 }
   1072 
   1073 bool SystemStatusPdr::equals(SystemStatusPdr& peer)
   1074 {
   1075     if (mFixInfoMask != peer.mFixInfoMask) {
   1076         return false;
   1077     }
   1078     return true;
   1079 }
   1080 
   1081 void SystemStatusPdr::dump()
   1082 {
   1083     LOC_LOGV("Pdr: u=%ld:%ld m=%x",
   1084              mUtcTime.tv_sec, mUtcTime.tv_nsec,
   1085              mFixInfoMask);
   1086     return;
   1087 }
   1088 
   1089 /******************************************************************************
   1090  SystemStatusNavData
   1091 ******************************************************************************/
   1092 SystemStatusNavData::SystemStatusNavData(const SystemStatusPQWP7& nmea)
   1093 {
   1094     for (uint32_t i=0; i<SV_ALL_NUM; i++) {
   1095         mNav[i] = nmea.mNav[i];
   1096     }
   1097 }
   1098 
   1099 bool SystemStatusNavData::equals(SystemStatusNavData& peer)
   1100 {
   1101     for (uint32_t i=0; i<SV_ALL_NUM; i++) {
   1102         if ((mNav[i].mType != peer.mNav[i].mType) ||
   1103             (mNav[i].mSource != peer.mNav[i].mSource) ||
   1104             (mNav[i].mAgeSec != peer.mNav[i].mAgeSec)) {
   1105             return false;
   1106         }
   1107     }
   1108     return true;
   1109 }
   1110 
   1111 void SystemStatusNavData::dump()
   1112 {
   1113     LOC_LOGV("NavData: u=%ld:%ld",
   1114             mUtcTime.tv_sec, mUtcTime.tv_nsec);
   1115     for (uint32_t i=0; i<SV_ALL_NUM; i++) {
   1116         LOC_LOGV("i=%d type=%d src=%d age=%d",
   1117             i, mNav[i].mType, mNav[i].mSource, mNav[i].mAgeSec);
   1118     }
   1119     return;
   1120 }
   1121 
   1122 /******************************************************************************
   1123  SystemStatusPositionFailure
   1124 ******************************************************************************/
   1125 SystemStatusPositionFailure::SystemStatusPositionFailure(const SystemStatusPQWS1& nmea) :
   1126     mFixInfoMask(nmea.mFixInfoMask),
   1127     mHepeLimit(nmea.mHepeLimit)
   1128 {
   1129 }
   1130 
   1131 bool SystemStatusPositionFailure::equals(SystemStatusPositionFailure& peer)
   1132 {
   1133     if ((mFixInfoMask != peer.mFixInfoMask) ||
   1134         (mHepeLimit != peer.mHepeLimit)) {
   1135         return false;
   1136     }
   1137     return true;
   1138 }
   1139 
   1140 void SystemStatusPositionFailure::dump()
   1141 {
   1142     LOC_LOGV("PositionFailure: u=%ld:%ld m=%d h=%d",
   1143              mUtcTime.tv_sec, mUtcTime.tv_nsec,
   1144              mFixInfoMask,
   1145              mHepeLimit);
   1146     return;
   1147 }
   1148 
   1149 /******************************************************************************
   1150  SystemStatusLocation
   1151 ******************************************************************************/
   1152 bool SystemStatusLocation::equals(SystemStatusLocation& peer)
   1153 {
   1154     if ((mLocation.gpsLocation.latitude != peer.mLocation.gpsLocation.latitude) ||
   1155         (mLocation.gpsLocation.longitude != peer.mLocation.gpsLocation.longitude) ||
   1156         (mLocation.gpsLocation.altitude != peer.mLocation.gpsLocation.altitude)) {
   1157         return false;
   1158     }
   1159     return true;
   1160 }
   1161 
   1162 void SystemStatusLocation::dump()
   1163 {
   1164     LOC_LOGV("Location: lat=%f lon=%f alt=%f spd=%f",
   1165              mLocation.gpsLocation.latitude,
   1166              mLocation.gpsLocation.longitude,
   1167              mLocation.gpsLocation.altitude,
   1168              mLocation.gpsLocation.speed);
   1169     return;
   1170 }
   1171 
   1172 /******************************************************************************
   1173  SystemStatus
   1174 ******************************************************************************/
   1175 pthread_mutex_t SystemStatus::mMutexSystemStatus = PTHREAD_MUTEX_INITIALIZER;
   1176 
   1177 SystemStatus::SystemStatus()
   1178 {
   1179     mCache.mLocation.clear();
   1180 
   1181     mCache.mTimeAndClock.clear();
   1182     mCache.mXoState.clear();
   1183     mCache.mRfAndParams.clear();
   1184     mCache.mErrRecovery.clear();
   1185 
   1186     mCache.mInjectedPosition.clear();
   1187     mCache.mBestPosition.clear();
   1188     mCache.mXtra.clear();
   1189     mCache.mEphemeris.clear();
   1190     mCache.mSvHealth.clear();
   1191     mCache.mPdr.clear();
   1192     mCache.mNavData.clear();
   1193 
   1194     mCache.mPositionFailure.clear();
   1195 }
   1196 
   1197 /******************************************************************************
   1198  SystemStatus - M1 functions
   1199 ******************************************************************************/
   1200 bool SystemStatus::setTimeAndCLock(const SystemStatusPQWM1& nmea)
   1201 {
   1202     SystemStatusTimeAndClock s(nmea);
   1203     if (!mCache.mTimeAndClock.empty() && mCache.mTimeAndClock.back().equals(s)) {
   1204         mCache.mTimeAndClock.back().mUtcReported = s.mUtcReported;
   1205     } else {
   1206         mCache.mTimeAndClock.push_back(s);
   1207         if (mCache.mTimeAndClock.size() > maxTimeAndClock) {
   1208             mCache.mTimeAndClock.erase(mCache.mTimeAndClock.begin());
   1209         }
   1210     }
   1211     return true;
   1212 }
   1213 
   1214 bool SystemStatus::setXoState(const SystemStatusPQWM1& nmea)
   1215 {
   1216     SystemStatusXoState s(nmea);
   1217     if (!mCache.mXoState.empty() && mCache.mXoState.back().equals(s)) {
   1218         mCache.mXoState.back().mUtcReported = s.mUtcReported;
   1219     } else {
   1220         mCache.mXoState.push_back(s);
   1221         if (mCache.mXoState.size() > maxXoState) {
   1222             mCache.mXoState.erase(mCache.mXoState.begin());
   1223         }
   1224     }
   1225     return true;
   1226 }
   1227 
   1228 bool SystemStatus::setRfAndParams(const SystemStatusPQWM1& nmea)
   1229 {
   1230     SystemStatusRfAndParams s(nmea);
   1231     if (!mCache.mRfAndParams.empty() && mCache.mRfAndParams.back().equals(s)) {
   1232         mCache.mRfAndParams.back().mUtcReported = s.mUtcReported;
   1233     } else {
   1234         mCache.mRfAndParams.push_back(s);
   1235         if (mCache.mRfAndParams.size() > maxRfAndParams) {
   1236             mCache.mRfAndParams.erase(mCache.mRfAndParams.begin());
   1237         }
   1238     }
   1239     return true;
   1240 }
   1241 
   1242 bool SystemStatus::setErrRecovery(const SystemStatusPQWM1& nmea)
   1243 {
   1244     SystemStatusErrRecovery s(nmea);
   1245     if (!mCache.mErrRecovery.empty() && mCache.mErrRecovery.back().equals(s)) {
   1246         mCache.mErrRecovery.back().mUtcReported = s.mUtcReported;
   1247     } else {
   1248         mCache.mErrRecovery.push_back(s);
   1249         if (mCache.mErrRecovery.size() > maxErrRecovery) {
   1250             mCache.mErrRecovery.erase(mCache.mErrRecovery.begin());
   1251         }
   1252     }
   1253     return true;
   1254 }
   1255 
   1256 /******************************************************************************
   1257  SystemStatus - Px functions
   1258 ******************************************************************************/
   1259 bool SystemStatus::setInjectedPosition(const SystemStatusPQWP1& nmea)
   1260 {
   1261     SystemStatusInjectedPosition s(nmea);
   1262     if (!mCache.mInjectedPosition.empty() && mCache.mInjectedPosition.back().equals(s)) {
   1263         mCache.mInjectedPosition.back().mUtcReported = s.mUtcReported;
   1264     } else {
   1265         mCache.mInjectedPosition.push_back(s);
   1266         if (mCache.mInjectedPosition.size() > maxInjectedPosition) {
   1267             mCache.mInjectedPosition.erase(mCache.mInjectedPosition.begin());
   1268         }
   1269     }
   1270     return true;
   1271 }
   1272 
   1273 bool SystemStatus::setBestPosition(const SystemStatusPQWP2& nmea)
   1274 {
   1275     SystemStatusBestPosition s(nmea);
   1276     if (!mCache.mBestPosition.empty() && mCache.mBestPosition.back().equals(s)) {
   1277         mCache.mBestPosition.back().mUtcReported = s.mUtcReported;
   1278     } else {
   1279         mCache.mBestPosition.push_back(s);
   1280         if (mCache.mBestPosition.size() > maxBestPosition) {
   1281             mCache.mBestPosition.erase(mCache.mBestPosition.begin());
   1282         }
   1283     }
   1284     return true;
   1285 }
   1286 
   1287 bool SystemStatus::setXtra(const SystemStatusPQWP3& nmea)
   1288 {
   1289     SystemStatusXtra s(nmea);
   1290     if (!mCache.mXtra.empty() && mCache.mXtra.back().equals(s)) {
   1291         mCache.mXtra.back().mUtcReported = s.mUtcReported;
   1292     } else {
   1293         mCache.mXtra.push_back(s);
   1294         if (mCache.mXtra.size() > maxXtra) {
   1295             mCache.mXtra.erase(mCache.mXtra.begin());
   1296         }
   1297     }
   1298     return true;
   1299 }
   1300 
   1301 bool SystemStatus::setEphemeris(const SystemStatusPQWP4& nmea)
   1302 {
   1303     SystemStatusEphemeris s(nmea);
   1304     if (!mCache.mEphemeris.empty() && mCache.mEphemeris.back().equals(s)) {
   1305         mCache.mEphemeris.back().mUtcReported = s.mUtcReported;
   1306     } else {
   1307         mCache.mEphemeris.push_back(s);
   1308         if (mCache.mEphemeris.size() > maxEphemeris) {
   1309             mCache.mEphemeris.erase(mCache.mEphemeris.begin());
   1310         }
   1311     }
   1312     return true;
   1313 }
   1314 
   1315 bool SystemStatus::setSvHealth(const SystemStatusPQWP5& nmea)
   1316 {
   1317     SystemStatusSvHealth s(nmea);
   1318     if (!mCache.mSvHealth.empty() && mCache.mSvHealth.back().equals(s)) {
   1319         mCache.mSvHealth.back().mUtcReported = s.mUtcReported;
   1320     } else {
   1321         mCache.mSvHealth.push_back(s);
   1322         if (mCache.mSvHealth.size() > maxSvHealth) {
   1323             mCache.mSvHealth.erase(mCache.mSvHealth.begin());
   1324         }
   1325     }
   1326     return true;
   1327 }
   1328 
   1329 bool SystemStatus::setPdr(const SystemStatusPQWP6& nmea)
   1330 {
   1331     SystemStatusPdr s(nmea);
   1332     if (!mCache.mPdr.empty() && mCache.mPdr.back().equals(s)) {
   1333         mCache.mPdr.back().mUtcReported = s.mUtcReported;
   1334     } else {
   1335         mCache.mPdr.push_back(s);
   1336         if (mCache.mPdr.size() > maxPdr) {
   1337             mCache.mPdr.erase(mCache.mPdr.begin());
   1338         }
   1339     }
   1340     return true;
   1341 }
   1342 
   1343 bool SystemStatus::setNavData(const SystemStatusPQWP7& nmea)
   1344 {
   1345     SystemStatusNavData s(nmea);
   1346     if (!mCache.mNavData.empty() && mCache.mNavData.back().equals(s)) {
   1347         mCache.mNavData.back().mUtcReported = s.mUtcReported;
   1348     } else {
   1349         mCache.mNavData.push_back(s);
   1350         if (mCache.mNavData.size() > maxNavData) {
   1351             mCache.mNavData.erase(mCache.mNavData.begin());
   1352         }
   1353     }
   1354     return true;
   1355 }
   1356 
   1357 /******************************************************************************
   1358  SystemStatus - Sx functions
   1359 ******************************************************************************/
   1360 bool SystemStatus::setPositionFailure(const SystemStatusPQWS1& nmea)
   1361 {
   1362     SystemStatusPositionFailure s(nmea);
   1363     if (!mCache.mPositionFailure.empty() && mCache.mPositionFailure.back().equals(s)) {
   1364         mCache.mPositionFailure.back().mUtcReported = s.mUtcReported;
   1365     } else {
   1366         mCache.mPositionFailure.push_back(s);
   1367         if (mCache.mPositionFailure.size() > maxPositionFailure) {
   1368             mCache.mPositionFailure.erase(mCache.mPositionFailure.begin());
   1369         }
   1370     }
   1371     return true;
   1372 }
   1373 
   1374 /******************************************************************************
   1375 @brief      API to set report data into internal buffer
   1376 
   1377 @param[In]  data pointer to the NMEA string
   1378 @param[In]  len  length of the NMEA string
   1379 
   1380 @return     true when successfully done
   1381 ******************************************************************************/
   1382 static uint32_t cnt = 0;
   1383 static uint32_t cnt_m1 = 0;
   1384 static uint32_t cnt_p1 = 0;
   1385 static uint32_t cnt_p2 = 0;
   1386 static uint32_t cnt_p3 = 0;
   1387 static uint32_t cnt_p4 = 0;
   1388 static uint32_t cnt_p5 = 0;
   1389 static uint32_t cnt_p6 = 0;
   1390 static uint32_t cnt_p7 = 0;
   1391 static uint32_t cnt_s1 = 0;
   1392 
   1393 bool SystemStatus::setNmeaString(const char *data, uint32_t len)
   1394 {
   1395     bool ret = false;
   1396     if (!loc_nmea_is_debug(data, len)) {
   1397         return false;
   1398     }
   1399 
   1400     char buf[SystemStatusNmeaBase::NMEA_MAXSIZE + 1] = { 0 };
   1401     strlcpy(buf, data, sizeof(buf));
   1402 
   1403     pthread_mutex_lock(&mMutexSystemStatus);
   1404 
   1405     // parse the received nmea strings here
   1406     if      (0 == strncmp(data, "$PQWM1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
   1407         SystemStatusPQWM1 s = SystemStatusPQWM1parser(buf, len).get();
   1408         ret  = setTimeAndCLock(s);
   1409         ret |= setXoState(s);
   1410         ret |= setRfAndParams(s);
   1411         ret |= setErrRecovery(s);
   1412         cnt_m1++;
   1413     }
   1414     else if (0 == strncmp(data, "$PQWP1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
   1415         ret = setInjectedPosition(SystemStatusPQWP1parser(buf, len).get());
   1416         cnt_p1++;
   1417     }
   1418     else if (0 == strncmp(data, "$PQWP2", SystemStatusNmeaBase::NMEA_MINSIZE)) {
   1419         ret = setBestPosition(SystemStatusPQWP2parser(buf, len).get());
   1420         cnt_p2++;
   1421     }
   1422     else if (0 == strncmp(data, "$PQWP3", SystemStatusNmeaBase::NMEA_MINSIZE)) {
   1423         ret = setXtra(SystemStatusPQWP3parser(buf, len).get());
   1424         cnt_p3++;
   1425     }
   1426     else if (0 == strncmp(data, "$PQWP4", SystemStatusNmeaBase::NMEA_MINSIZE)) {
   1427         ret = setEphemeris(SystemStatusPQWP4parser(buf, len).get());
   1428         cnt_p4++;
   1429     }
   1430     else if (0 == strncmp(data, "$PQWP5", SystemStatusNmeaBase::NMEA_MINSIZE)) {
   1431         ret = setSvHealth(SystemStatusPQWP5parser(buf, len).get());
   1432         cnt_p5++;
   1433     }
   1434     else if (0 == strncmp(data, "$PQWP6", SystemStatusNmeaBase::NMEA_MINSIZE)) {
   1435         ret = setPdr(SystemStatusPQWP6parser(buf, len).get());
   1436         cnt_p6++;
   1437     }
   1438     else if (0 == strncmp(data, "$PQWP7", SystemStatusNmeaBase::NMEA_MINSIZE)) {
   1439         ret = setNavData(SystemStatusPQWP7parser(buf, len).get());
   1440         cnt_p7++;
   1441     }
   1442     else if (0 == strncmp(data, "$PQWS1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
   1443         ret = setPositionFailure(SystemStatusPQWS1parser(buf, len).get());
   1444         cnt_s1++;
   1445     }
   1446     else {
   1447         // do nothing
   1448     }
   1449     cnt++;
   1450     LOC_LOGV("setNmeaString: cnt=%d M:%d 1:%d 2:%d 3:%d 4:%d 5:%d 6:%d 7:%d S:%d",
   1451              cnt,
   1452              cnt_m1,
   1453              cnt_p1,
   1454              cnt_p2,
   1455              cnt_p3,
   1456              cnt_p4,
   1457              cnt_p5,
   1458              cnt_p6,
   1459              cnt_p7,
   1460              cnt_s1);
   1461 
   1462     pthread_mutex_unlock(&mMutexSystemStatus);
   1463     return ret;
   1464 }
   1465 
   1466 /******************************************************************************
   1467 @brief      API to set report position data into internal buffer
   1468 
   1469 @param[In]  UlpLocation
   1470 
   1471 @return     true when successfully done
   1472 ******************************************************************************/
   1473 bool SystemStatus::eventPosition(const UlpLocation& location,
   1474                                  const GpsLocationExtended& locationEx)
   1475 {
   1476     SystemStatusLocation s(location, locationEx);
   1477     if (!mCache.mLocation.empty() && mCache.mLocation.back().equals(s)) {
   1478         mCache.mLocation.back().mUtcReported = s.mUtcReported;
   1479     }
   1480     else {
   1481         mCache.mLocation.push_back(s);
   1482         if (mCache.mLocation.size() > maxLocation) {
   1483             mCache.mLocation.erase(mCache.mLocation.begin());
   1484         }
   1485     }
   1486     LOC_LOGV("eventPosition - lat=%f lon=%f alt=%f speed=%f",
   1487              s.mLocation.gpsLocation.latitude,
   1488              s.mLocation.gpsLocation.longitude,
   1489              s.mLocation.gpsLocation.altitude,
   1490              s.mLocation.gpsLocation.speed);
   1491     return true;
   1492 }
   1493 
   1494 /******************************************************************************
   1495 @brief      API to get report data into a given buffer
   1496 
   1497 @param[In]  reference to report buffer
   1498 @param[In]  bool flag to identify latest only or entire buffer
   1499 
   1500 @return     true when successfully done
   1501 ******************************************************************************/
   1502 bool SystemStatus::getReport(SystemStatusReports& report, bool isLatestOnly) const
   1503 {
   1504     pthread_mutex_lock(&mMutexSystemStatus);
   1505 
   1506     if (isLatestOnly) {
   1507         // push back only the latest report and return it
   1508         report.mLocation.clear();
   1509         if (mCache.mLocation.size() >= 1) {
   1510             report.mLocation.push_back(mCache.mLocation.back());
   1511             report.mLocation.back().dump();
   1512         }
   1513 
   1514         report.mTimeAndClock.clear();
   1515         if (mCache.mTimeAndClock.size() >= 1) {
   1516             report.mTimeAndClock.push_back(mCache.mTimeAndClock.back());
   1517             report.mTimeAndClock.back().dump();
   1518         }
   1519         report.mXoState.clear();
   1520         if (mCache.mXoState.size() >= 1) {
   1521             report.mXoState.push_back(mCache.mXoState.back());
   1522             report.mXoState.back().dump();
   1523         }
   1524         report.mRfAndParams.clear();
   1525         if (mCache.mRfAndParams.size() >= 1) {
   1526             report.mRfAndParams.push_back(mCache.mRfAndParams.back());
   1527             report.mRfAndParams.back().dump();
   1528         }
   1529         report.mErrRecovery.clear();
   1530         if (mCache.mErrRecovery.size() >= 1) {
   1531             report.mErrRecovery.push_back(mCache.mErrRecovery.back());
   1532             report.mErrRecovery.back().dump();
   1533         }
   1534 
   1535         report.mInjectedPosition.clear();
   1536         if (mCache.mInjectedPosition.size() >= 1) {
   1537             report.mInjectedPosition.push_back(mCache.mInjectedPosition.back());
   1538             report.mInjectedPosition.back().dump();
   1539         }
   1540         report.mBestPosition.clear();
   1541         if (mCache.mBestPosition.size() >= 1) {
   1542             report.mBestPosition.push_back(mCache.mBestPosition.back());
   1543             report.mBestPosition.back().dump();
   1544         }
   1545         report.mXtra.clear();
   1546         if (mCache.mXtra.size() >= 1) {
   1547             report.mXtra.push_back(mCache.mXtra.back());
   1548             report.mXtra.back().dump();
   1549         }
   1550         report.mEphemeris.clear();
   1551         if (mCache.mEphemeris.size() >= 1) {
   1552             report.mEphemeris.push_back(mCache.mEphemeris.back());
   1553             report.mEphemeris.back().dump();
   1554         }
   1555         report.mSvHealth.clear();
   1556         if (mCache.mSvHealth.size() >= 1) {
   1557             report.mSvHealth.push_back(mCache.mSvHealth.back());
   1558             report.mSvHealth.back().dump();
   1559         }
   1560         report.mPdr.clear();
   1561         if (mCache.mPdr.size() >= 1) {
   1562             report.mPdr.push_back(mCache.mPdr.back());
   1563             report.mPdr.back().dump();
   1564         }
   1565         report.mNavData.clear();
   1566         if (mCache.mNavData.size() >= 1) {
   1567             report.mNavData.push_back(mCache.mNavData.back());
   1568             report.mNavData.back().dump();
   1569         }
   1570 
   1571         report.mPositionFailure.clear();
   1572         if (mCache.mPositionFailure.size() >= 1) {
   1573             report.mPositionFailure.push_back(mCache.mPositionFailure.back());
   1574             report.mPositionFailure.back().dump();
   1575         }
   1576     }
   1577     else {
   1578         // copy entire reports and return them
   1579         report.mLocation.clear();
   1580 
   1581         report.mTimeAndClock.clear();
   1582         report.mXoState.clear();
   1583         report.mRfAndParams.clear();
   1584         report.mErrRecovery.clear();
   1585 
   1586         report.mInjectedPosition.clear();
   1587         report.mBestPosition.clear();
   1588         report.mXtra.clear();
   1589         report.mEphemeris.clear();
   1590         report.mSvHealth.clear();
   1591         report.mPdr.clear();
   1592         report.mNavData.clear();
   1593 
   1594         report.mPositionFailure.clear();
   1595         report = mCache;
   1596     }
   1597 
   1598     pthread_mutex_unlock(&mMutexSystemStatus);
   1599     return true;
   1600 }
   1601 
   1602 /******************************************************************************
   1603 @brief      API to set default report data
   1604 
   1605 @param[In]  none
   1606 
   1607 @return     true when successfully done
   1608 ******************************************************************************/
   1609 bool SystemStatus::setDefaultReport(void)
   1610 {
   1611     pthread_mutex_lock(&mMutexSystemStatus);
   1612 
   1613     mCache.mLocation.push_back(SystemStatusLocation());
   1614     if (mCache.mLocation.size() > maxLocation) {
   1615         mCache.mLocation.erase(mCache.mLocation.begin());
   1616     }
   1617 
   1618     mCache.mTimeAndClock.push_back(SystemStatusTimeAndClock());
   1619     if (mCache.mTimeAndClock.size() > maxTimeAndClock) {
   1620         mCache.mTimeAndClock.erase(mCache.mTimeAndClock.begin());
   1621     }
   1622     mCache.mXoState.push_back(SystemStatusXoState());
   1623     if (mCache.mXoState.size() > maxXoState) {
   1624         mCache.mXoState.erase(mCache.mXoState.begin());
   1625     }
   1626     mCache.mRfAndParams.push_back(SystemStatusRfAndParams());
   1627     if (mCache.mRfAndParams.size() > maxRfAndParams) {
   1628         mCache.mRfAndParams.erase(mCache.mRfAndParams.begin());
   1629     }
   1630     mCache.mErrRecovery.push_back(SystemStatusErrRecovery());
   1631     if (mCache.mErrRecovery.size() > maxErrRecovery) {
   1632         mCache.mErrRecovery.erase(mCache.mErrRecovery.begin());
   1633     }
   1634 
   1635     mCache.mInjectedPosition.push_back(SystemStatusInjectedPosition());
   1636     if (mCache.mInjectedPosition.size() > maxInjectedPosition) {
   1637         mCache.mInjectedPosition.erase(mCache.mInjectedPosition.begin());
   1638     }
   1639     mCache.mBestPosition.push_back(SystemStatusBestPosition());
   1640     if (mCache.mBestPosition.size() > maxBestPosition) {
   1641         mCache.mBestPosition.erase(mCache.mBestPosition.begin());
   1642     }
   1643     mCache.mXtra.push_back(SystemStatusXtra());
   1644     if (mCache.mXtra.size() > maxXtra) {
   1645         mCache.mXtra.erase(mCache.mXtra.begin());
   1646     }
   1647     mCache.mEphemeris.push_back(SystemStatusEphemeris());
   1648     if (mCache.mEphemeris.size() > maxEphemeris) {
   1649         mCache.mEphemeris.erase(mCache.mEphemeris.begin());
   1650     }
   1651     mCache.mSvHealth.push_back(SystemStatusSvHealth());
   1652     if (mCache.mSvHealth.size() > maxSvHealth) {
   1653         mCache.mSvHealth.erase(mCache.mSvHealth.begin());
   1654     }
   1655     mCache.mPdr.push_back(SystemStatusPdr());
   1656     if (mCache.mPdr.size() > maxPdr) {
   1657         mCache.mPdr.erase(mCache.mPdr.begin());
   1658     }
   1659     mCache.mNavData.push_back(SystemStatusNavData());
   1660     if (mCache.mNavData.size() > maxNavData) {
   1661         mCache.mNavData.erase(mCache.mNavData.begin());
   1662     }
   1663 
   1664     mCache.mPositionFailure.push_back(SystemStatusPositionFailure());
   1665     if (mCache.mPositionFailure.size() > maxPositionFailure) {
   1666         mCache.mPositionFailure.erase(mCache.mPositionFailure.begin());
   1667     }
   1668 
   1669     pthread_mutex_unlock(&mMutexSystemStatus);
   1670     return true;
   1671 }
   1672 
   1673 } // namespace loc_core
   1674 
   1675