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         eLeapSeconds = 23,
162         eLeapSecUnc = 24,
163         eGloBpAmpI = 25,
164         eGloBpAmpQ = 26,
165         eBdsBpAmpI = 27,
166         eBdsBpAmpQ = 28,
167         eGalBpAmpI = 29,
168         eGalBpAmpQ = 30,
169         eMax0 = eGalBpAmpQ,
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 (!report.empty() && report.back().equals(static_cast<TYPE_ITEM&>(s.collate(report.back())))) {
1350         // there is no change - just update reported timestamp
1351         report.back().mUtcReported = s.mUtcReported;
1352         return false;
1353     }
1354 
1355     // first event or updated
1356     report.push_back(s);
1357     if (report.size() > s.maxItem) {
1358         report.erase(report.begin());
1359     }
1360     return true;
1361 }
1362 
1363 template <typename TYPE_REPORT, typename TYPE_ITEM>
setDefaultIteminReport(TYPE_REPORT & report,const TYPE_ITEM & s)1364 void SystemStatus::setDefaultIteminReport(TYPE_REPORT& report, const TYPE_ITEM& s)
1365 {
1366     report.push_back(s);
1367     if (report.size() > s.maxItem) {
1368         report.erase(report.begin());
1369     }
1370 }
1371 
1372 template <typename TYPE_REPORT, typename TYPE_ITEM>
getIteminReport(TYPE_REPORT & reportout,const TYPE_ITEM & c) const1373 void SystemStatus::getIteminReport(TYPE_REPORT& reportout, const TYPE_ITEM& c) const
1374 {
1375     reportout.clear();
1376     if (c.size() >= 1) {
1377         reportout.push_back(c.back());
1378         reportout.back().dump();
1379     }
1380 }
1381 
1382 /******************************************************************************
1383 @brief      API to set report data into internal buffer
1384 
1385 @param[In]  data pointer to the NMEA string
1386 @param[In]  len  length of the NMEA string
1387 
1388 @return     true when the NMEA is consumed by the method.
1389 ******************************************************************************/
setNmeaString(const char * data,uint32_t len)1390 bool SystemStatus::setNmeaString(const char *data, uint32_t len)
1391 {
1392     if (!loc_nmea_is_debug(data, len)) {
1393         return false;
1394     }
1395 
1396     char buf[SystemStatusNmeaBase::NMEA_MAXSIZE + 1] = { 0 };
1397     strlcpy(buf, data, sizeof(buf));
1398 
1399     pthread_mutex_lock(&mMutexSystemStatus);
1400 
1401     // parse the received nmea strings here
1402     if (0 == strncmp(data, "$PQWM1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1403         SystemStatusPQWM1 s = SystemStatusPQWM1parser(buf, len).get();
1404         setIteminReport(mCache.mTimeAndClock, SystemStatusTimeAndClock(s));
1405         setIteminReport(mCache.mXoState, SystemStatusXoState(s));
1406         setIteminReport(mCache.mRfAndParams, SystemStatusRfAndParams(s));
1407         setIteminReport(mCache.mErrRecovery, SystemStatusErrRecovery(s));
1408     }
1409     else if (0 == strncmp(data, "$PQWP1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1410         setIteminReport(mCache.mInjectedPosition,
1411                 SystemStatusInjectedPosition(SystemStatusPQWP1parser(buf, len).get()));
1412     }
1413     else if (0 == strncmp(data, "$PQWP2", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1414         setIteminReport(mCache.mBestPosition,
1415                 SystemStatusBestPosition(SystemStatusPQWP2parser(buf, len).get()));
1416     }
1417     else if (0 == strncmp(data, "$PQWP3", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1418         setIteminReport(mCache.mXtra,
1419                 SystemStatusXtra(SystemStatusPQWP3parser(buf, len).get()));
1420     }
1421     else if (0 == strncmp(data, "$PQWP4", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1422         setIteminReport(mCache.mEphemeris,
1423                 SystemStatusEphemeris(SystemStatusPQWP4parser(buf, len).get()));
1424     }
1425     else if (0 == strncmp(data, "$PQWP5", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1426         setIteminReport(mCache.mSvHealth,
1427                 SystemStatusSvHealth(SystemStatusPQWP5parser(buf, len).get()));
1428     }
1429     else if (0 == strncmp(data, "$PQWP6", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1430         setIteminReport(mCache.mPdr,
1431                 SystemStatusPdr(SystemStatusPQWP6parser(buf, len).get()));
1432     }
1433     else if (0 == strncmp(data, "$PQWP7", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1434         setIteminReport(mCache.mNavData,
1435                 SystemStatusNavData(SystemStatusPQWP7parser(buf, len).get()));
1436     }
1437     else if (0 == strncmp(data, "$PQWS1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1438         setIteminReport(mCache.mPositionFailure,
1439                 SystemStatusPositionFailure(SystemStatusPQWS1parser(buf, len).get()));
1440     }
1441     else {
1442         // do nothing
1443     }
1444 
1445     pthread_mutex_unlock(&mMutexSystemStatus);
1446     return true;
1447 }
1448 
1449 /******************************************************************************
1450 @brief      API to set report position data into internal buffer
1451 
1452 @param[In]  UlpLocation
1453 
1454 @return     true when successfully done
1455 ******************************************************************************/
eventPosition(const UlpLocation & location,const GpsLocationExtended & locationEx)1456 bool SystemStatus::eventPosition(const UlpLocation& location,
1457                                  const GpsLocationExtended& locationEx)
1458 {
1459     bool ret = false;
1460     pthread_mutex_lock(&mMutexSystemStatus);
1461 
1462     ret = setIteminReport(mCache.mLocation, SystemStatusLocation(location, locationEx));
1463     LOC_LOGV("eventPosition - lat=%f lon=%f alt=%f speed=%f",
1464              location.gpsLocation.latitude,
1465              location.gpsLocation.longitude,
1466              location.gpsLocation.altitude,
1467              location.gpsLocation.speed);
1468 
1469     pthread_mutex_unlock(&mMutexSystemStatus);
1470     return ret;
1471 }
1472 
1473 /******************************************************************************
1474 @brief      API to set report DataItem event into internal buffer
1475 
1476 @param[In]  DataItem
1477 
1478 @return     true when info is updatated
1479 ******************************************************************************/
eventDataItemNotify(IDataItemCore * dataitem)1480 bool SystemStatus::eventDataItemNotify(IDataItemCore* dataitem)
1481 {
1482     bool ret = false;
1483     pthread_mutex_lock(&mMutexSystemStatus);
1484     switch(dataitem->getId())
1485     {
1486         case AIRPLANEMODE_DATA_ITEM_ID:
1487             ret = setIteminReport(mCache.mAirplaneMode,
1488                     SystemStatusAirplaneMode(*(static_cast<AirplaneModeDataItemBase*>(dataitem))));
1489             break;
1490         case ENH_DATA_ITEM_ID:
1491             ret = setIteminReport(mCache.mENH,
1492                     SystemStatusENH(*(static_cast<ENHDataItemBase*>(dataitem))));
1493             break;
1494         case GPSSTATE_DATA_ITEM_ID:
1495             ret = setIteminReport(mCache.mGPSState,
1496                     SystemStatusGpsState(*(static_cast<GPSStateDataItemBase*>(dataitem))));
1497             break;
1498         case NLPSTATUS_DATA_ITEM_ID:
1499             ret = setIteminReport(mCache.mNLPStatus,
1500                     SystemStatusNLPStatus(*(static_cast<NLPStatusDataItemBase*>(dataitem))));
1501             break;
1502         case WIFIHARDWARESTATE_DATA_ITEM_ID:
1503             ret = setIteminReport(mCache.mWifiHardwareState,
1504                     SystemStatusWifiHardwareState(*(static_cast<WifiHardwareStateDataItemBase*>(dataitem))));
1505             break;
1506         case NETWORKINFO_DATA_ITEM_ID:
1507             ret = setIteminReport(mCache.mNetworkInfo,
1508                     SystemStatusNetworkInfo(*(static_cast<NetworkInfoDataItemBase*>(dataitem))));
1509             break;
1510         case RILSERVICEINFO_DATA_ITEM_ID:
1511             ret = setIteminReport(mCache.mRilServiceInfo,
1512                     SystemStatusServiceInfo(*(static_cast<RilServiceInfoDataItemBase*>(dataitem))));
1513             break;
1514         case RILCELLINFO_DATA_ITEM_ID:
1515             ret = setIteminReport(mCache.mRilCellInfo,
1516                     SystemStatusRilCellInfo(*(static_cast<RilCellInfoDataItemBase*>(dataitem))));
1517             break;
1518         case SERVICESTATUS_DATA_ITEM_ID:
1519             ret = setIteminReport(mCache.mServiceStatus,
1520                     SystemStatusServiceStatus(*(static_cast<ServiceStatusDataItemBase*>(dataitem))));
1521             break;
1522         case MODEL_DATA_ITEM_ID:
1523             ret = setIteminReport(mCache.mModel,
1524                     SystemStatusModel(*(static_cast<ModelDataItemBase*>(dataitem))));
1525             break;
1526         case MANUFACTURER_DATA_ITEM_ID:
1527             ret = setIteminReport(mCache.mManufacturer,
1528                     SystemStatusManufacturer(*(static_cast<ManufacturerDataItemBase*>(dataitem))));
1529             break;
1530         case ASSISTED_GPS_DATA_ITEM_ID:
1531             ret = setIteminReport(mCache.mAssistedGps,
1532                     SystemStatusAssistedGps(*(static_cast<AssistedGpsDataItemBase*>(dataitem))));
1533             break;
1534         case SCREEN_STATE_DATA_ITEM_ID:
1535             ret = setIteminReport(mCache.mScreenState,
1536                     SystemStatusScreenState(*(static_cast<ScreenStateDataItemBase*>(dataitem))));
1537             break;
1538         case POWER_CONNECTED_STATE_DATA_ITEM_ID:
1539             ret = setIteminReport(mCache.mPowerConnectState,
1540                     SystemStatusPowerConnectState(*(static_cast<PowerConnectStateDataItemBase*>(dataitem))));
1541             break;
1542         case TIMEZONE_CHANGE_DATA_ITEM_ID:
1543             ret = setIteminReport(mCache.mTimeZoneChange,
1544                     SystemStatusTimeZoneChange(*(static_cast<TimeZoneChangeDataItemBase*>(dataitem))));
1545             break;
1546         case TIME_CHANGE_DATA_ITEM_ID:
1547             ret = setIteminReport(mCache.mTimeChange,
1548                     SystemStatusTimeChange(*(static_cast<TimeChangeDataItemBase*>(dataitem))));
1549             break;
1550         case WIFI_SUPPLICANT_STATUS_DATA_ITEM_ID:
1551             ret = setIteminReport(mCache.mWifiSupplicantStatus,
1552                     SystemStatusWifiSupplicantStatus(*(static_cast<WifiSupplicantStatusDataItemBase*>(dataitem))));
1553             break;
1554         case SHUTDOWN_STATE_DATA_ITEM_ID:
1555             ret = setIteminReport(mCache.mShutdownState,
1556                     SystemStatusShutdownState(*(static_cast<ShutdownStateDataItemBase*>(dataitem))));
1557             break;
1558         case TAC_DATA_ITEM_ID:
1559             ret = setIteminReport(mCache.mTac,
1560                     SystemStatusTac(*(static_cast<TacDataItemBase*>(dataitem))));
1561             break;
1562         case MCCMNC_DATA_ITEM_ID:
1563             ret = setIteminReport(mCache.mMccMnc,
1564                     SystemStatusMccMnc(*(static_cast<MccmncDataItemBase*>(dataitem))));
1565             break;
1566         case BTLE_SCAN_DATA_ITEM_ID:
1567             ret = setIteminReport(mCache.mBtDeviceScanDetail,
1568                     SystemStatusBtDeviceScanDetail(*(static_cast<BtDeviceScanDetailsDataItemBase*>(dataitem))));
1569             break;
1570         case BT_SCAN_DATA_ITEM_ID:
1571             ret = setIteminReport(mCache.mBtLeDeviceScanDetail,
1572                     SystemStatusBtleDeviceScanDetail(*(static_cast<BtLeDeviceScanDetailsDataItemBase*>(dataitem))));
1573             break;
1574         default:
1575             break;
1576     }
1577     pthread_mutex_unlock(&mMutexSystemStatus);
1578     return ret;
1579 }
1580 
1581 /******************************************************************************
1582 @brief      API to get report data into a given buffer
1583 
1584 @param[In]  reference to report buffer
1585 @param[In]  bool flag to identify latest only or entire buffer
1586 
1587 @return     true when successfully done
1588 ******************************************************************************/
getReport(SystemStatusReports & report,bool isLatestOnly) const1589 bool SystemStatus::getReport(SystemStatusReports& report, bool isLatestOnly) const
1590 {
1591     pthread_mutex_lock(&mMutexSystemStatus);
1592 
1593     if (isLatestOnly) {
1594         // push back only the latest report and return it
1595         getIteminReport(report.mLocation, mCache.mLocation);
1596 
1597         getIteminReport(report.mTimeAndClock, mCache.mTimeAndClock);
1598         getIteminReport(report.mXoState, mCache.mXoState);
1599         getIteminReport(report.mRfAndParams, mCache.mRfAndParams);
1600         getIteminReport(report.mErrRecovery, mCache.mErrRecovery);
1601 
1602         getIteminReport(report.mInjectedPosition, mCache.mInjectedPosition);
1603         getIteminReport(report.mBestPosition, mCache.mBestPosition);
1604         getIteminReport(report.mXtra, mCache.mXtra);
1605         getIteminReport(report.mEphemeris, mCache.mEphemeris);
1606         getIteminReport(report.mSvHealth, mCache.mSvHealth);
1607         getIteminReport(report.mPdr, mCache.mPdr);
1608         getIteminReport(report.mNavData, mCache.mNavData);
1609 
1610         getIteminReport(report.mPositionFailure, mCache.mPositionFailure);
1611 
1612         getIteminReport(report.mAirplaneMode, mCache.mAirplaneMode);
1613         getIteminReport(report.mENH, mCache.mENH);
1614         getIteminReport(report.mGPSState, mCache.mGPSState);
1615         getIteminReport(report.mNLPStatus, mCache.mNLPStatus);
1616         getIteminReport(report.mWifiHardwareState, mCache.mWifiHardwareState);
1617         getIteminReport(report.mNetworkInfo, mCache.mNetworkInfo);
1618         getIteminReport(report.mRilServiceInfo, mCache.mRilServiceInfo);
1619         getIteminReport(report.mRilCellInfo, mCache.mRilCellInfo);
1620         getIteminReport(report.mServiceStatus, mCache.mServiceStatus);
1621         getIteminReport(report.mModel, mCache.mModel);
1622         getIteminReport(report.mManufacturer, mCache.mManufacturer);
1623         getIteminReport(report.mAssistedGps, mCache.mAssistedGps);
1624         getIteminReport(report.mScreenState, mCache.mScreenState);
1625         getIteminReport(report.mPowerConnectState, mCache.mPowerConnectState);
1626         getIteminReport(report.mTimeZoneChange, mCache.mTimeZoneChange);
1627         getIteminReport(report.mTimeChange, mCache.mTimeChange);
1628         getIteminReport(report.mWifiSupplicantStatus, mCache.mWifiSupplicantStatus);
1629         getIteminReport(report.mShutdownState, mCache.mShutdownState);
1630         getIteminReport(report.mTac, mCache.mTac);
1631         getIteminReport(report.mMccMnc, mCache.mMccMnc);
1632         getIteminReport(report.mBtDeviceScanDetail, mCache.mBtDeviceScanDetail);
1633         getIteminReport(report.mBtLeDeviceScanDetail, mCache.mBtLeDeviceScanDetail);
1634     }
1635     else {
1636         // copy entire reports and return them
1637         report.mLocation.clear();
1638 
1639         report.mTimeAndClock.clear();
1640         report.mXoState.clear();
1641         report.mRfAndParams.clear();
1642         report.mErrRecovery.clear();
1643 
1644         report.mInjectedPosition.clear();
1645         report.mBestPosition.clear();
1646         report.mXtra.clear();
1647         report.mEphemeris.clear();
1648         report.mSvHealth.clear();
1649         report.mPdr.clear();
1650         report.mNavData.clear();
1651 
1652         report.mPositionFailure.clear();
1653 
1654         report.mAirplaneMode.clear();
1655         report.mENH.clear();
1656         report.mGPSState.clear();
1657         report.mNLPStatus.clear();
1658         report.mWifiHardwareState.clear();
1659         report.mNetworkInfo.clear();
1660         report.mRilServiceInfo.clear();
1661         report.mRilCellInfo.clear();
1662         report.mServiceStatus.clear();
1663         report.mModel.clear();
1664         report.mManufacturer.clear();
1665         report.mAssistedGps.clear();
1666         report.mScreenState.clear();
1667         report.mPowerConnectState.clear();
1668         report.mTimeZoneChange.clear();
1669         report.mTimeChange.clear();
1670         report.mWifiSupplicantStatus.clear();
1671         report.mShutdownState.clear();
1672         report.mTac.clear();
1673         report.mMccMnc.clear();
1674         report.mBtDeviceScanDetail.clear();
1675         report.mBtLeDeviceScanDetail.clear();
1676 
1677         report = mCache;
1678     }
1679 
1680     pthread_mutex_unlock(&mMutexSystemStatus);
1681     return true;
1682 }
1683 
1684 /******************************************************************************
1685 @brief      API to set default report data
1686 
1687 @param[In]  none
1688 
1689 @return     true when successfully done
1690 ******************************************************************************/
setDefaultGnssEngineStates(void)1691 bool SystemStatus::setDefaultGnssEngineStates(void)
1692 {
1693     pthread_mutex_lock(&mMutexSystemStatus);
1694 
1695     setDefaultIteminReport(mCache.mLocation, SystemStatusLocation());
1696 
1697     setDefaultIteminReport(mCache.mTimeAndClock, SystemStatusTimeAndClock());
1698     setDefaultIteminReport(mCache.mXoState, SystemStatusXoState());
1699     setDefaultIteminReport(mCache.mRfAndParams, SystemStatusRfAndParams());
1700     setDefaultIteminReport(mCache.mErrRecovery, SystemStatusErrRecovery());
1701 
1702     setDefaultIteminReport(mCache.mInjectedPosition, SystemStatusInjectedPosition());
1703     setDefaultIteminReport(mCache.mBestPosition, SystemStatusBestPosition());
1704     setDefaultIteminReport(mCache.mXtra, SystemStatusXtra());
1705     setDefaultIteminReport(mCache.mEphemeris, SystemStatusEphemeris());
1706     setDefaultIteminReport(mCache.mSvHealth, SystemStatusSvHealth());
1707     setDefaultIteminReport(mCache.mPdr, SystemStatusPdr());
1708     setDefaultIteminReport(mCache.mNavData, SystemStatusNavData());
1709 
1710     setDefaultIteminReport(mCache.mPositionFailure, SystemStatusPositionFailure());
1711 
1712     pthread_mutex_unlock(&mMutexSystemStatus);
1713     return true;
1714 }
1715 
1716 /******************************************************************************
1717 @brief      API to handle connection status update event from GnssRil
1718 
1719 @param[In]  Connection status
1720 
1721 @return     true when successfully done
1722 ******************************************************************************/
eventConnectionStatus(bool connected,int8_t type,bool roaming,NetworkHandle networkHandle)1723 bool SystemStatus::eventConnectionStatus(bool connected, int8_t type,
1724                                          bool roaming, NetworkHandle networkHandle)
1725 {
1726     // send networkinof dataitem to systemstatus observer clients
1727     SystemStatusNetworkInfo s(type, "", "", connected, roaming,
1728                               (uint64_t) networkHandle);
1729     mSysStatusObsvr.notify({&s});
1730 
1731     return true;
1732 }
1733 
1734 /******************************************************************************
1735 @brief      API to update power connect state
1736 
1737 @param[In]  power connect status
1738 
1739 @return     true when successfully done
1740 ******************************************************************************/
updatePowerConnectState(bool charging)1741 bool SystemStatus::updatePowerConnectState(bool charging)
1742 {
1743     SystemStatusPowerConnectState s(charging);
1744     mSysStatusObsvr.notify({&s});
1745     return true;
1746 }
1747 } // namespace loc_core
1748 
1749