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 
SystemStatusNmeaBase(const char * str_in,uint32_t len_in)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 
~SystemStatusNmeaBase()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:
getGpsWeek()156     inline uint16_t   getGpsWeek()    { return mM1.mGpsWeek; }
getGpsTowMs()157     inline uint32_t   getGpsTowMs()   { return mM1.mGpsTowMs; }
getTimeValid()158     inline uint8_t    getTimeValid()  { return mM1.mTimeValid; }
getTimeSource()159     inline uint8_t    getTimeSource() { return mM1.mTimeSource; }
getTimeUnc()160     inline int32_t    getTimeUnc()    { return mM1.mTimeUnc; }
getClockFreqBias()161     inline int32_t    getClockFreqBias() { return mM1.mClockFreqBias; }
getClockFreqBiasUnc()162     inline int32_t    getClockFreqBiasUnc() { return mM1.mClockFreqBiasUnc; }
getXoState()163     inline uint8_t    getXoState()    { return mM1.mXoState;}
getPgaGain()164     inline int32_t    getPgaGain()    { return mM1.mPgaGain;          }
getGpsBpAmpI()165     inline uint32_t   getGpsBpAmpI()  { return mM1.mGpsBpAmpI;        }
getGpsBpAmpQ()166     inline uint32_t   getGpsBpAmpQ()  { return mM1.mGpsBpAmpQ;        }
getAdcI()167     inline uint32_t   getAdcI()       { return mM1.mAdcI;             }
getAdcQ()168     inline uint32_t   getAdcQ()       { return mM1.mAdcQ;             }
getJammerGps()169     inline uint32_t   getJammerGps()  { return mM1.mJammerGps;        }
getJammerGlo()170     inline uint32_t   getJammerGlo()  { return mM1.mJammerGlo;        }
getJammerBds()171     inline uint32_t   getJammerBds()  { return mM1.mJammerBds;        }
getJammerGal()172     inline uint32_t   getJammerGal()  { return mM1.mJammerGal;        }
getAgcGps()173     inline uint32_t   getAgcGps()     { return mM1.mAgcGps;           }
getAgcGlo()174     inline uint32_t   getAgcGlo()     { return mM1.mAgcGlo;           }
getAgcBds()175     inline uint32_t   getAgcBds()     { return mM1.mAgcBds;           }
getAgcGal()176     inline uint32_t   getAgcGal()     { return mM1.mAgcGal;           }
getRecErrorRecovery()177     inline uint32_t   getRecErrorRecovery() { return mM1.mRecErrorRecovery; }
getLeapSeconds()178     inline int32_t    getLeapSeconds(){ return mM1.mLeapSeconds; }
getLeapSecUnc()179     inline int32_t    getLeapSecUnc() { return mM1.mLeapSecUnc; }
180 
SystemStatusPQWM1parser(const char * str_in,uint32_t len_in)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 
get()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:
getEpiValidity()253     inline uint8_t    getEpiValidity() { return mP1.mEpiValidity;      }
getEpiLat()254     inline float      getEpiLat() { return mP1.mEpiLat;           }
getEpiLon()255     inline float      getEpiLon() { return mP1.mEpiLon;           }
getEpiAlt()256     inline float      getEpiAlt() { return mP1.mEpiAlt;           }
getEpiHepe()257     inline float      getEpiHepe() { return mP1.mEpiHepe;          }
getEpiAltUnc()258     inline float      getEpiAltUnc() { return mP1.mEpiAltUnc;        }
getEpiSrc()259     inline uint8_t    getEpiSrc() { return mP1.mEpiSrc;           }
260 
SystemStatusPQWP1parser(const char * str_in,uint32_t len_in)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 
get()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:
getBestLat()310     inline float      getBestLat() { return mP2.mBestLat;          }
getBestLon()311     inline float      getBestLon() { return mP2.mBestLon;          }
getBestAlt()312     inline float      getBestAlt() { return mP2.mBestAlt;          }
getBestHepe()313     inline float      getBestHepe() { return mP2.mBestHepe;         }
getBestAltUnc()314     inline float      getBestAltUnc() { return mP2.mBestAltUnc;       }
315 
SystemStatusPQWP2parser(const char * str_in,uint32_t len_in)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 
get()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:
getXtraValid()375     inline uint8_t    getXtraValid() { return mP3.mXtraValidMask;   }
getGpsXtraAge()376     inline uint32_t   getGpsXtraAge() { return mP3.mGpsXtraAge;       }
getGloXtraAge()377     inline uint32_t   getGloXtraAge() { return mP3.mGloXtraAge;       }
getBdsXtraAge()378     inline uint32_t   getBdsXtraAge() { return mP3.mBdsXtraAge;       }
getGalXtraAge()379     inline uint32_t   getGalXtraAge() { return mP3.mGalXtraAge;       }
getQzssXtraAge()380     inline uint32_t   getQzssXtraAge() { return mP3.mQzssXtraAge;      }
getGpsXtraValid()381     inline uint32_t   getGpsXtraValid() { return mP3.mGpsXtraValid;     }
getGloXtraValid()382     inline uint32_t   getGloXtraValid() { return mP3.mGloXtraValid;     }
getBdsXtraValid()383     inline uint64_t   getBdsXtraValid() { return mP3.mBdsXtraValid;     }
getGalXtraValid()384     inline uint64_t   getGalXtraValid() { return mP3.mGalXtraValid;     }
getQzssXtraValid()385     inline uint8_t    getQzssXtraValid() { return mP3.mQzssXtraValid;    }
386 
SystemStatusPQWP3parser(const char * str_in,uint32_t len_in)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 
get()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:
getGpsEpheValid()440     inline uint32_t   getGpsEpheValid() { return mP4.mGpsEpheValid;     }
getGloEpheValid()441     inline uint32_t   getGloEpheValid() { return mP4.mGloEpheValid;     }
getBdsEpheValid()442     inline uint64_t   getBdsEpheValid() { return mP4.mBdsEpheValid;     }
getGalEpheValid()443     inline uint64_t   getGalEpheValid() { return mP4.mGalEpheValid;     }
getQzssEpheValid()444     inline uint8_t    getQzssEpheValid() { return mP4.mQzssEpheValid;    }
445 
SystemStatusPQWP4parser(const char * str_in,uint32_t len_in)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 
get()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:
getGpsUnknownMask()513     inline uint32_t   getGpsUnknownMask() { return mP5.mGpsUnknownMask;   }
getGloUnknownMask()514     inline uint32_t   getGloUnknownMask() { return mP5.mGloUnknownMask;   }
getBdsUnknownMask()515     inline uint64_t   getBdsUnknownMask() { return mP5.mBdsUnknownMask;   }
getGalUnknownMask()516     inline uint64_t   getGalUnknownMask() { return mP5.mGalUnknownMask;   }
getQzssUnknownMask()517     inline uint8_t    getQzssUnknownMask() { return mP5.mQzssUnknownMask;  }
getGpsGoodMask()518     inline uint32_t   getGpsGoodMask() { return mP5.mGpsGoodMask;      }
getGloGoodMask()519     inline uint32_t   getGloGoodMask() { return mP5.mGloGoodMask;      }
getBdsGoodMask()520     inline uint64_t   getBdsGoodMask() { return mP5.mBdsGoodMask;      }
getGalGoodMask()521     inline uint64_t   getGalGoodMask() { return mP5.mGalGoodMask;      }
getQzssGoodMask()522     inline uint8_t    getQzssGoodMask() { return mP5.mQzssGoodMask;     }
getGpsBadMask()523     inline uint32_t   getGpsBadMask() { return mP5.mGpsBadMask;       }
getGloBadMask()524     inline uint32_t   getGloBadMask() { return mP5.mGloBadMask;       }
getBdsBadMask()525     inline uint64_t   getBdsBadMask() { return mP5.mBdsBadMask;       }
getGalBadMask()526     inline uint64_t   getGalBadMask() { return mP5.mGalBadMask;       }
getQzssBadMask()527     inline uint8_t    getQzssBadMask() { return mP5.mQzssBadMask;      }
528 
SystemStatusPQWP5parser(const char * str_in,uint32_t len_in)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 
get()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:
getFixInfoMask()578     inline uint32_t   getFixInfoMask() { return mP6.mFixInfoMask;      }
579 
SystemStatusPQWP6parser(const char * str_in,uint32_t len_in)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 
get()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:
SystemStatusPQWP7parser(const char * str_in,uint32_t len_in)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 
get()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:
getFixInfoMask()655     inline uint16_t   getFixInfoMask() { return mS1.mFixInfoMask;      }
getHepeLimit()656     inline uint32_t   getHepeLimit()   { return mS1.mHepeLimit;      }
657 
SystemStatusPQWS1parser(const char * str_in,uint32_t len_in)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 
get()669     inline SystemStatusPQWS1& get() { return mS1;}
670 };
671 
672 /******************************************************************************
673  SystemStatusTimeAndClock
674 ******************************************************************************/
SystemStatusTimeAndClock(const SystemStatusPQWM1 & nmea)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 
equals(SystemStatusTimeAndClock & peer)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 
dump()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 ******************************************************************************/
SystemStatusXoState(const SystemStatusPQWM1 & nmea)723 SystemStatusXoState::SystemStatusXoState(const SystemStatusPQWM1& nmea) :
724     mXoState(nmea.mXoState)
725 {
726 }
727 
equals(SystemStatusXoState & peer)728 bool SystemStatusXoState::equals(SystemStatusXoState& peer)
729 {
730     if (mXoState != peer.mXoState) {
731         return false;
732     }
733     return true;
734 }
735 
dump()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 ******************************************************************************/
SystemStatusRfAndParams(const SystemStatusPQWM1 & nmea)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 
equals(SystemStatusRfAndParams & peer)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 
dump()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 ******************************************************************************/
SystemStatusErrRecovery(const SystemStatusPQWM1 & nmea)809 SystemStatusErrRecovery::SystemStatusErrRecovery(const SystemStatusPQWM1& nmea) :
810     mRecErrorRecovery(nmea.mRecErrorRecovery)
811 {
812 }
813 
equals(SystemStatusErrRecovery & peer)814 bool SystemStatusErrRecovery::equals(SystemStatusErrRecovery& peer)
815 {
816     if (mRecErrorRecovery != peer.mRecErrorRecovery) {
817         return false;
818     }
819     return true;
820 }
821 
dump()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 ******************************************************************************/
SystemStatusInjectedPosition(const SystemStatusPQWP1 & nmea)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 
equals(SystemStatusInjectedPosition & peer)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 
dump()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 ******************************************************************************/
SystemStatusBestPosition(const SystemStatusPQWP2 & nmea)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 
equals(SystemStatusBestPosition & peer)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 
dump()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 ******************************************************************************/
SystemStatusXtra(const SystemStatusPQWP3 & nmea)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 
equals(SystemStatusXtra & peer)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 
dump()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 ******************************************************************************/
SystemStatusEphemeris(const SystemStatusPQWP4 & nmea)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 
equals(SystemStatusEphemeris & peer)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 
dump()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 ******************************************************************************/
SystemStatusSvHealth(const SystemStatusPQWP5 & nmea)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 
equals(SystemStatusSvHealth & peer)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 
dump()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 ******************************************************************************/
SystemStatusPdr(const SystemStatusPQWP6 & nmea)1068 SystemStatusPdr::SystemStatusPdr(const SystemStatusPQWP6& nmea) :
1069     mFixInfoMask(nmea.mFixInfoMask)
1070 {
1071 }
1072 
equals(SystemStatusPdr & peer)1073 bool SystemStatusPdr::equals(SystemStatusPdr& peer)
1074 {
1075     if (mFixInfoMask != peer.mFixInfoMask) {
1076         return false;
1077     }
1078     return true;
1079 }
1080 
dump()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 ******************************************************************************/
SystemStatusNavData(const SystemStatusPQWP7 & nmea)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 
equals(SystemStatusNavData & peer)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 
dump()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 ******************************************************************************/
SystemStatusPositionFailure(const SystemStatusPQWS1 & nmea)1125 SystemStatusPositionFailure::SystemStatusPositionFailure(const SystemStatusPQWS1& nmea) :
1126     mFixInfoMask(nmea.mFixInfoMask),
1127     mHepeLimit(nmea.mHepeLimit)
1128 {
1129 }
1130 
equals(SystemStatusPositionFailure & peer)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 
dump()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 ******************************************************************************/
equals(SystemStatusLocation & peer)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 
dump()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 
SystemStatus()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 ******************************************************************************/
setTimeAndCLock(const SystemStatusPQWM1 & nmea)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 
setXoState(const SystemStatusPQWM1 & nmea)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 
setRfAndParams(const SystemStatusPQWM1 & nmea)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 
setErrRecovery(const SystemStatusPQWM1 & nmea)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 ******************************************************************************/
setInjectedPosition(const SystemStatusPQWP1 & nmea)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 
setBestPosition(const SystemStatusPQWP2 & nmea)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 
setXtra(const SystemStatusPQWP3 & nmea)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 
setEphemeris(const SystemStatusPQWP4 & nmea)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 
setSvHealth(const SystemStatusPQWP5 & nmea)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 
setPdr(const SystemStatusPQWP6 & nmea)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 
setNavData(const SystemStatusPQWP7 & nmea)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 ******************************************************************************/
setPositionFailure(const SystemStatusPQWS1 & nmea)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 
setNmeaString(const char * data,uint32_t len)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 ******************************************************************************/
eventPosition(const UlpLocation & location,const GpsLocationExtended & locationEx)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 ******************************************************************************/
getReport(SystemStatusReports & report,bool isLatestOnly) const1502 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 ******************************************************************************/
setDefaultReport(void)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