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