xref: /aosp_15_r20/hardware/interfaces/gnss/common/utils/default/NmeaFixInfo.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker  *
4*4d7e907cSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker  *
8*4d7e907cSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker  *
10*4d7e907cSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker  * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker  */
16*4d7e907cSAndroid Build Coastguard Worker 
17*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "NmeaFixInfo"
18*4d7e907cSAndroid Build Coastguard Worker 
19*4d7e907cSAndroid Build Coastguard Worker #include <Constants.h>
20*4d7e907cSAndroid Build Coastguard Worker #include <NmeaFixInfo.h>
21*4d7e907cSAndroid Build Coastguard Worker #include <Utils.h>
22*4d7e907cSAndroid Build Coastguard Worker #include <log/log.h>
23*4d7e907cSAndroid Build Coastguard Worker #include <sys/stat.h>
24*4d7e907cSAndroid Build Coastguard Worker #include <sys/types.h>
25*4d7e907cSAndroid Build Coastguard Worker #include <unistd.h>
26*4d7e907cSAndroid Build Coastguard Worker #include <utils/SystemClock.h>
27*4d7e907cSAndroid Build Coastguard Worker #include <limits>
28*4d7e907cSAndroid Build Coastguard Worker #include <sstream>
29*4d7e907cSAndroid Build Coastguard Worker #include <string>
30*4d7e907cSAndroid Build Coastguard Worker #include <vector>
31*4d7e907cSAndroid Build Coastguard Worker 
32*4d7e907cSAndroid Build Coastguard Worker namespace android {
33*4d7e907cSAndroid Build Coastguard Worker namespace hardware {
34*4d7e907cSAndroid Build Coastguard Worker namespace gnss {
35*4d7e907cSAndroid Build Coastguard Worker namespace common {
36*4d7e907cSAndroid Build Coastguard Worker 
37*4d7e907cSAndroid Build Coastguard Worker using aidl::android::hardware::gnss::ElapsedRealtime;
38*4d7e907cSAndroid Build Coastguard Worker using aidl::android::hardware::gnss::GnssLocation;
39*4d7e907cSAndroid Build Coastguard Worker 
NmeaFixInfo()40*4d7e907cSAndroid Build Coastguard Worker NmeaFixInfo::NmeaFixInfo() : hasGMCRecord(false), hasGGARecord(false) {}
41*4d7e907cSAndroid Build Coastguard Worker 
getAltitudeMeters() const42*4d7e907cSAndroid Build Coastguard Worker float NmeaFixInfo::getAltitudeMeters() const {
43*4d7e907cSAndroid Build Coastguard Worker     return altitudeMeters;
44*4d7e907cSAndroid Build Coastguard Worker }
45*4d7e907cSAndroid Build Coastguard Worker 
checkAndConvertToFloat(const std::string & sentence)46*4d7e907cSAndroid Build Coastguard Worker float NmeaFixInfo::checkAndConvertToFloat(const std::string& sentence) {
47*4d7e907cSAndroid Build Coastguard Worker     if (sentence.empty()) {
48*4d7e907cSAndroid Build Coastguard Worker         return std::numeric_limits<float>::quiet_NaN();
49*4d7e907cSAndroid Build Coastguard Worker     }
50*4d7e907cSAndroid Build Coastguard Worker     return std::stof(sentence);
51*4d7e907cSAndroid Build Coastguard Worker }
52*4d7e907cSAndroid Build Coastguard Worker 
getBearingAccuracyDegrees() const53*4d7e907cSAndroid Build Coastguard Worker float NmeaFixInfo::getBearingAccuracyDegrees() const {
54*4d7e907cSAndroid Build Coastguard Worker     // Current NMEA doesn't contains beaing accuracy inforamtion
55*4d7e907cSAndroid Build Coastguard Worker     return kMockBearingAccuracyDegrees;
56*4d7e907cSAndroid Build Coastguard Worker }
getBearingDegrees() const57*4d7e907cSAndroid Build Coastguard Worker float NmeaFixInfo::getBearingDegrees() const {
58*4d7e907cSAndroid Build Coastguard Worker     return bearingDegrees;
59*4d7e907cSAndroid Build Coastguard Worker }
60*4d7e907cSAndroid Build Coastguard Worker 
getHorizontalAccuracyMeters() const61*4d7e907cSAndroid Build Coastguard Worker float NmeaFixInfo::getHorizontalAccuracyMeters() const {
62*4d7e907cSAndroid Build Coastguard Worker     // Current NMEA doesn't contains horizontal accuracy inforamtion
63*4d7e907cSAndroid Build Coastguard Worker     return kMockHorizontalAccuracyMeters;
64*4d7e907cSAndroid Build Coastguard Worker }
65*4d7e907cSAndroid Build Coastguard Worker 
getLatDeg() const66*4d7e907cSAndroid Build Coastguard Worker float NmeaFixInfo::getLatDeg() const {
67*4d7e907cSAndroid Build Coastguard Worker     return latDeg;
68*4d7e907cSAndroid Build Coastguard Worker }
69*4d7e907cSAndroid Build Coastguard Worker 
getLngDeg() const70*4d7e907cSAndroid Build Coastguard Worker float NmeaFixInfo::getLngDeg() const {
71*4d7e907cSAndroid Build Coastguard Worker     return lngDeg;
72*4d7e907cSAndroid Build Coastguard Worker }
73*4d7e907cSAndroid Build Coastguard Worker 
getSpeedAccuracyMetersPerSecond() const74*4d7e907cSAndroid Build Coastguard Worker float NmeaFixInfo::getSpeedAccuracyMetersPerSecond() const {
75*4d7e907cSAndroid Build Coastguard Worker     // Current NMEA doesn't contains speed accuracy inforamtion
76*4d7e907cSAndroid Build Coastguard Worker     return kMockSpeedAccuracyMetersPerSecond;
77*4d7e907cSAndroid Build Coastguard Worker }
78*4d7e907cSAndroid Build Coastguard Worker 
getSpeedMetersPerSec() const79*4d7e907cSAndroid Build Coastguard Worker float NmeaFixInfo::getSpeedMetersPerSec() const {
80*4d7e907cSAndroid Build Coastguard Worker     return speedMetersPerSec;
81*4d7e907cSAndroid Build Coastguard Worker }
82*4d7e907cSAndroid Build Coastguard Worker 
getTimestamp() const83*4d7e907cSAndroid Build Coastguard Worker int64_t NmeaFixInfo::getTimestamp() const {
84*4d7e907cSAndroid Build Coastguard Worker     return timestamp;
85*4d7e907cSAndroid Build Coastguard Worker }
86*4d7e907cSAndroid Build Coastguard Worker 
getVerticalAccuracyMeters() const87*4d7e907cSAndroid Build Coastguard Worker float NmeaFixInfo::getVerticalAccuracyMeters() const {
88*4d7e907cSAndroid Build Coastguard Worker     // Current NMEA doesn't contains vertical accuracy inforamtion
89*4d7e907cSAndroid Build Coastguard Worker     return kMockVerticalAccuracyMeters;
90*4d7e907cSAndroid Build Coastguard Worker }
91*4d7e907cSAndroid Build Coastguard Worker 
nmeaPartsToTimestamp(const std::string & timeStr,const std::string & dateStr)92*4d7e907cSAndroid Build Coastguard Worker int64_t NmeaFixInfo::nmeaPartsToTimestamp(const std::string& timeStr, const std::string& dateStr) {
93*4d7e907cSAndroid Build Coastguard Worker     /**
94*4d7e907cSAndroid Build Coastguard Worker      * In NMEA format, the full time can only get from the $GPRMC record, see
95*4d7e907cSAndroid Build Coastguard Worker      * the following example:
96*4d7e907cSAndroid Build Coastguard Worker      * $GPRMC,213204.00,A,3725.371240,N,12205.589239,W,000.0,000.0,290819,,,A*49
97*4d7e907cSAndroid Build Coastguard Worker      * the datetime is stored in two parts, 213204 and 290819, which means
98*4d7e907cSAndroid Build Coastguard Worker      * 2019/08/29 21:32:04, however for in unix the year starts from 1900, we
99*4d7e907cSAndroid Build Coastguard Worker      * need to add the offset.
100*4d7e907cSAndroid Build Coastguard Worker      */
101*4d7e907cSAndroid Build Coastguard Worker     struct tm tm;
102*4d7e907cSAndroid Build Coastguard Worker     const int32_t unixYearOffset = 100;
103*4d7e907cSAndroid Build Coastguard Worker     tm.tm_mday = std::stoi(dateStr.substr(0, 2).c_str());
104*4d7e907cSAndroid Build Coastguard Worker     tm.tm_mon = std::stoi(dateStr.substr(2, 2).c_str()) - 1;
105*4d7e907cSAndroid Build Coastguard Worker     tm.tm_year = std::stoi(dateStr.substr(4, 2).c_str()) + unixYearOffset;
106*4d7e907cSAndroid Build Coastguard Worker     tm.tm_hour = std::stoi(timeStr.substr(0, 2).c_str());
107*4d7e907cSAndroid Build Coastguard Worker     tm.tm_min = std::stoi(timeStr.substr(2, 2).c_str());
108*4d7e907cSAndroid Build Coastguard Worker     tm.tm_sec = std::stoi(timeStr.substr(4, 2).c_str());
109*4d7e907cSAndroid Build Coastguard Worker     return static_cast<int64_t>(mktime(&tm) - timezone);
110*4d7e907cSAndroid Build Coastguard Worker }
111*4d7e907cSAndroid Build Coastguard Worker 
isValidFix() const112*4d7e907cSAndroid Build Coastguard Worker bool NmeaFixInfo::isValidFix() const {
113*4d7e907cSAndroid Build Coastguard Worker     return hasGMCRecord && hasGGARecord;
114*4d7e907cSAndroid Build Coastguard Worker }
115*4d7e907cSAndroid Build Coastguard Worker 
parseGGALine(const std::vector<std::string> & sentenceValues)116*4d7e907cSAndroid Build Coastguard Worker void NmeaFixInfo::parseGGALine(const std::vector<std::string>& sentenceValues) {
117*4d7e907cSAndroid Build Coastguard Worker     if (sentenceValues.size() == 0 || sentenceValues[0].compare(GPGA_RECORD_TAG) != 0) {
118*4d7e907cSAndroid Build Coastguard Worker         return;
119*4d7e907cSAndroid Build Coastguard Worker     }
120*4d7e907cSAndroid Build Coastguard Worker     // LatDeg, need covert to degree, if it is 'N', should be negative value
121*4d7e907cSAndroid Build Coastguard Worker     this->latDeg = std::stof(sentenceValues[2].substr(0, 2)) +
122*4d7e907cSAndroid Build Coastguard Worker                    (std::stof(sentenceValues[2].substr(2)) / 60.0);
123*4d7e907cSAndroid Build Coastguard Worker     if (sentenceValues[3].compare("N") != 0) {
124*4d7e907cSAndroid Build Coastguard Worker         this->latDeg *= -1;
125*4d7e907cSAndroid Build Coastguard Worker     }
126*4d7e907cSAndroid Build Coastguard Worker 
127*4d7e907cSAndroid Build Coastguard Worker     // LngDeg, need covert to degree, if it is 'E', should be negative value
128*4d7e907cSAndroid Build Coastguard Worker     this->lngDeg = std::stof(sentenceValues[4].substr(0, 3)) +
129*4d7e907cSAndroid Build Coastguard Worker                    std::stof(sentenceValues[4].substr(3)) / 60.0;
130*4d7e907cSAndroid Build Coastguard Worker     if (sentenceValues[5].compare("E") != 0) {
131*4d7e907cSAndroid Build Coastguard Worker         this->lngDeg *= -1;
132*4d7e907cSAndroid Build Coastguard Worker     }
133*4d7e907cSAndroid Build Coastguard Worker 
134*4d7e907cSAndroid Build Coastguard Worker     this->altitudeMeters = std::stof(sentenceValues[9]);
135*4d7e907cSAndroid Build Coastguard Worker 
136*4d7e907cSAndroid Build Coastguard Worker     this->hDop = sentenceValues[8].empty() ? std::numeric_limits<float>::quiet_NaN()
137*4d7e907cSAndroid Build Coastguard Worker                                            : std::stof(sentenceValues[8]);
138*4d7e907cSAndroid Build Coastguard Worker     this->hasGGARecord = true;
139*4d7e907cSAndroid Build Coastguard Worker }
140*4d7e907cSAndroid Build Coastguard Worker 
parseRMCLine(const std::vector<std::string> & sentenceValues)141*4d7e907cSAndroid Build Coastguard Worker void NmeaFixInfo::parseRMCLine(const std::vector<std::string>& sentenceValues) {
142*4d7e907cSAndroid Build Coastguard Worker     if (sentenceValues.size() == 0 || sentenceValues[0].compare(GPRMC_RECORD_TAG) != 0) {
143*4d7e907cSAndroid Build Coastguard Worker         return;
144*4d7e907cSAndroid Build Coastguard Worker     }
145*4d7e907cSAndroid Build Coastguard Worker     this->speedMetersPerSec = checkAndConvertToFloat(sentenceValues[7]);
146*4d7e907cSAndroid Build Coastguard Worker     this->bearingDegrees = checkAndConvertToFloat(sentenceValues[8]);
147*4d7e907cSAndroid Build Coastguard Worker     this->timestamp = nmeaPartsToTimestamp(sentenceValues[1], sentenceValues[9]);
148*4d7e907cSAndroid Build Coastguard Worker     this->hasGMCRecord = true;
149*4d7e907cSAndroid Build Coastguard Worker }
150*4d7e907cSAndroid Build Coastguard Worker 
151*4d7e907cSAndroid Build Coastguard Worker /** invalid the current NmeaFixInfo */
reset()152*4d7e907cSAndroid Build Coastguard Worker void NmeaFixInfo::reset() {
153*4d7e907cSAndroid Build Coastguard Worker     this->altitudeMeters = 0;
154*4d7e907cSAndroid Build Coastguard Worker     this->bearingDegrees = 0;
155*4d7e907cSAndroid Build Coastguard Worker     this->fixId = 0;
156*4d7e907cSAndroid Build Coastguard Worker     this->hasGMCRecord = false;
157*4d7e907cSAndroid Build Coastguard Worker     this->hasGGARecord = false;
158*4d7e907cSAndroid Build Coastguard Worker     this->latDeg = 0;
159*4d7e907cSAndroid Build Coastguard Worker     this->lngDeg = 0;
160*4d7e907cSAndroid Build Coastguard Worker     this->hDop = 0;
161*4d7e907cSAndroid Build Coastguard Worker     this->vDop = 0;
162*4d7e907cSAndroid Build Coastguard Worker     this->satelliteCount = 0;
163*4d7e907cSAndroid Build Coastguard Worker     this->speedMetersPerSec = 0;
164*4d7e907cSAndroid Build Coastguard Worker     this->timestamp = 0;
165*4d7e907cSAndroid Build Coastguard Worker }
166*4d7e907cSAndroid Build Coastguard Worker 
splitStr(const std::string & line,const char & delimiter,std::vector<std::string> & out)167*4d7e907cSAndroid Build Coastguard Worker void NmeaFixInfo::splitStr(const std::string& line, const char& delimiter,
168*4d7e907cSAndroid Build Coastguard Worker                            std::vector<std::string>& out) {
169*4d7e907cSAndroid Build Coastguard Worker     std::istringstream iss(line);
170*4d7e907cSAndroid Build Coastguard Worker     std::string item;
171*4d7e907cSAndroid Build Coastguard Worker     while (std::getline(iss, item, delimiter)) {
172*4d7e907cSAndroid Build Coastguard Worker         out.push_back(item);
173*4d7e907cSAndroid Build Coastguard Worker     }
174*4d7e907cSAndroid Build Coastguard Worker }
175*4d7e907cSAndroid Build Coastguard Worker 
operator =(const NmeaFixInfo & rhs)176*4d7e907cSAndroid Build Coastguard Worker NmeaFixInfo& NmeaFixInfo::operator=(const NmeaFixInfo& rhs) {
177*4d7e907cSAndroid Build Coastguard Worker     if (this == &rhs) return *this;
178*4d7e907cSAndroid Build Coastguard Worker     this->altitudeMeters = rhs.altitudeMeters;
179*4d7e907cSAndroid Build Coastguard Worker     this->bearingDegrees = rhs.bearingDegrees;
180*4d7e907cSAndroid Build Coastguard Worker     this->fixId = rhs.fixId;
181*4d7e907cSAndroid Build Coastguard Worker     this->hasGMCRecord = rhs.hasGMCRecord;
182*4d7e907cSAndroid Build Coastguard Worker     this->hasGGARecord = rhs.hasGGARecord;
183*4d7e907cSAndroid Build Coastguard Worker     this->hDop = rhs.hDop;
184*4d7e907cSAndroid Build Coastguard Worker     this->vDop = rhs.vDop;
185*4d7e907cSAndroid Build Coastguard Worker     this->latDeg = rhs.latDeg;
186*4d7e907cSAndroid Build Coastguard Worker     this->lngDeg = rhs.lngDeg;
187*4d7e907cSAndroid Build Coastguard Worker     this->satelliteCount = rhs.satelliteCount;
188*4d7e907cSAndroid Build Coastguard Worker     this->speedMetersPerSec = rhs.speedMetersPerSec;
189*4d7e907cSAndroid Build Coastguard Worker     this->timestamp = rhs.timestamp;
190*4d7e907cSAndroid Build Coastguard Worker 
191*4d7e907cSAndroid Build Coastguard Worker     return *this;
192*4d7e907cSAndroid Build Coastguard Worker }
193*4d7e907cSAndroid Build Coastguard Worker 
194*4d7e907cSAndroid Build Coastguard Worker /**
195*4d7e907cSAndroid Build Coastguard Worker  * Parses the input string in NMEA format and convert to GnssLocation.
196*4d7e907cSAndroid Build Coastguard Worker  * Currently version only cares about $GPGGA and $GPRMC records. but we
197*4d7e907cSAndroid Build Coastguard Worker  * can easily extend to other types supported by NMEA if needed.
198*4d7e907cSAndroid Build Coastguard Worker  */
getLocationFromInputStr(const std::string & inputStr)199*4d7e907cSAndroid Build Coastguard Worker std::unique_ptr<V2_0::GnssLocation> NmeaFixInfo::getLocationFromInputStr(
200*4d7e907cSAndroid Build Coastguard Worker         const std::string& inputStr) {
201*4d7e907cSAndroid Build Coastguard Worker     std::vector<std::string> nmeaRecords;
202*4d7e907cSAndroid Build Coastguard Worker     splitStr(inputStr, LINE_SEPARATOR, nmeaRecords);
203*4d7e907cSAndroid Build Coastguard Worker     NmeaFixInfo nmeaFixInfo;
204*4d7e907cSAndroid Build Coastguard Worker     NmeaFixInfo candidateFixInfo;
205*4d7e907cSAndroid Build Coastguard Worker     uint32_t fixId = 0;
206*4d7e907cSAndroid Build Coastguard Worker     double lastTimeStamp = 0;
207*4d7e907cSAndroid Build Coastguard Worker     for (const auto& line : nmeaRecords) {
208*4d7e907cSAndroid Build Coastguard Worker         if (line.compare(0, strlen(GPGA_RECORD_TAG), GPGA_RECORD_TAG) != 0 &&
209*4d7e907cSAndroid Build Coastguard Worker             line.compare(0, strlen(GPRMC_RECORD_TAG), GPRMC_RECORD_TAG) != 0) {
210*4d7e907cSAndroid Build Coastguard Worker             continue;
211*4d7e907cSAndroid Build Coastguard Worker         }
212*4d7e907cSAndroid Build Coastguard Worker         std::vector<std::string> sentenceValues;
213*4d7e907cSAndroid Build Coastguard Worker         splitStr(line, COMMA_SEPARATOR, sentenceValues);
214*4d7e907cSAndroid Build Coastguard Worker         if (sentenceValues.size() < MIN_COL_NUM) {
215*4d7e907cSAndroid Build Coastguard Worker             continue;
216*4d7e907cSAndroid Build Coastguard Worker         }
217*4d7e907cSAndroid Build Coastguard Worker         double currentTimeStamp = std::stof(sentenceValues[1]);
218*4d7e907cSAndroid Build Coastguard Worker         // If see a new timestamp, report correct location.
219*4d7e907cSAndroid Build Coastguard Worker         if ((currentTimeStamp - lastTimeStamp) > TIMESTAMP_EPSILON &&
220*4d7e907cSAndroid Build Coastguard Worker             candidateFixInfo.isValidFix()) {
221*4d7e907cSAndroid Build Coastguard Worker             nmeaFixInfo = candidateFixInfo;
222*4d7e907cSAndroid Build Coastguard Worker             candidateFixInfo.reset();
223*4d7e907cSAndroid Build Coastguard Worker             fixId++;
224*4d7e907cSAndroid Build Coastguard Worker         }
225*4d7e907cSAndroid Build Coastguard Worker         if (line.compare(0, strlen(GPGA_RECORD_TAG), GPGA_RECORD_TAG) == 0) {
226*4d7e907cSAndroid Build Coastguard Worker             candidateFixInfo.fixId = fixId;
227*4d7e907cSAndroid Build Coastguard Worker             candidateFixInfo.parseGGALine(sentenceValues);
228*4d7e907cSAndroid Build Coastguard Worker         } else if (line.compare(0, strlen(GPRMC_RECORD_TAG), GPRMC_RECORD_TAG) == 0) {
229*4d7e907cSAndroid Build Coastguard Worker             candidateFixInfo.parseRMCLine(sentenceValues);
230*4d7e907cSAndroid Build Coastguard Worker         }
231*4d7e907cSAndroid Build Coastguard Worker     }
232*4d7e907cSAndroid Build Coastguard Worker     if (candidateFixInfo.isValidFix()) {
233*4d7e907cSAndroid Build Coastguard Worker         nmeaFixInfo = candidateFixInfo;
234*4d7e907cSAndroid Build Coastguard Worker         candidateFixInfo.reset();
235*4d7e907cSAndroid Build Coastguard Worker     }
236*4d7e907cSAndroid Build Coastguard Worker     if (!nmeaFixInfo.isValidFix()) {
237*4d7e907cSAndroid Build Coastguard Worker         return nullptr;
238*4d7e907cSAndroid Build Coastguard Worker     }
239*4d7e907cSAndroid Build Coastguard Worker     return nmeaFixInfo.toGnssLocation();
240*4d7e907cSAndroid Build Coastguard Worker }
241*4d7e907cSAndroid Build Coastguard Worker 
242*4d7e907cSAndroid Build Coastguard Worker /**
243*4d7e907cSAndroid Build Coastguard Worker  * Convert V2_0::GnssLocation to aidl::GnssLocation.
244*4d7e907cSAndroid Build Coastguard Worker  */
getAidlLocationFromInputStr(const std::string & inputStr)245*4d7e907cSAndroid Build Coastguard Worker std::unique_ptr<GnssLocation> NmeaFixInfo::getAidlLocationFromInputStr(
246*4d7e907cSAndroid Build Coastguard Worker         const std::string& inputStr) {
247*4d7e907cSAndroid Build Coastguard Worker     std::unique_ptr<V2_0::GnssLocation> locationV2 = getLocationFromInputStr(inputStr);
248*4d7e907cSAndroid Build Coastguard Worker     if (locationV2 == nullptr) {
249*4d7e907cSAndroid Build Coastguard Worker         return nullptr;
250*4d7e907cSAndroid Build Coastguard Worker     }
251*4d7e907cSAndroid Build Coastguard Worker 
252*4d7e907cSAndroid Build Coastguard Worker     ElapsedRealtime elapsedRealtime = {
253*4d7e907cSAndroid Build Coastguard Worker             .flags = ElapsedRealtime::HAS_TIMESTAMP_NS | ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS,
254*4d7e907cSAndroid Build Coastguard Worker             .timestampNs = ::android::elapsedRealtimeNano(),
255*4d7e907cSAndroid Build Coastguard Worker             // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
256*4d7e907cSAndroid Build Coastguard Worker             // In an actual implementation provide an estimate of the synchronization uncertainty
257*4d7e907cSAndroid Build Coastguard Worker             // or don't set the field.
258*4d7e907cSAndroid Build Coastguard Worker             .timeUncertaintyNs = 1020400};
259*4d7e907cSAndroid Build Coastguard Worker 
260*4d7e907cSAndroid Build Coastguard Worker     GnssLocation location = {
261*4d7e907cSAndroid Build Coastguard Worker             .gnssLocationFlags = locationV2->v1_0.gnssLocationFlags,
262*4d7e907cSAndroid Build Coastguard Worker             .latitudeDegrees = locationV2->v1_0.latitudeDegrees,
263*4d7e907cSAndroid Build Coastguard Worker             .longitudeDegrees = locationV2->v1_0.longitudeDegrees,
264*4d7e907cSAndroid Build Coastguard Worker             .altitudeMeters = locationV2->v1_0.altitudeMeters,
265*4d7e907cSAndroid Build Coastguard Worker             .speedMetersPerSec = locationV2->v1_0.speedMetersPerSec,
266*4d7e907cSAndroid Build Coastguard Worker             .bearingDegrees = locationV2->v1_0.bearingDegrees,
267*4d7e907cSAndroid Build Coastguard Worker             .horizontalAccuracyMeters = locationV2->v1_0.horizontalAccuracyMeters,
268*4d7e907cSAndroid Build Coastguard Worker             .verticalAccuracyMeters = locationV2->v1_0.verticalAccuracyMeters,
269*4d7e907cSAndroid Build Coastguard Worker             .speedAccuracyMetersPerSecond = locationV2->v1_0.speedAccuracyMetersPerSecond,
270*4d7e907cSAndroid Build Coastguard Worker             .bearingAccuracyDegrees = locationV2->v1_0.bearingAccuracyDegrees,
271*4d7e907cSAndroid Build Coastguard Worker             .timestampMillis = locationV2->v1_0.timestamp,
272*4d7e907cSAndroid Build Coastguard Worker             .elapsedRealtime = elapsedRealtime};
273*4d7e907cSAndroid Build Coastguard Worker     return std::make_unique<GnssLocation>(location);
274*4d7e907cSAndroid Build Coastguard Worker }
275*4d7e907cSAndroid Build Coastguard Worker 
276*4d7e907cSAndroid Build Coastguard Worker /**
277*4d7e907cSAndroid Build Coastguard Worker  * Parses the input string in NMEA format and convert to GnssLocation.
278*4d7e907cSAndroid Build Coastguard Worker  */
toGnssLocation() const279*4d7e907cSAndroid Build Coastguard Worker std::unique_ptr<V2_0::GnssLocation> NmeaFixInfo::toGnssLocation() const {
280*4d7e907cSAndroid Build Coastguard Worker     const V2_0::ElapsedRealtime currentOsTimestamp = {
281*4d7e907cSAndroid Build Coastguard Worker             .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
282*4d7e907cSAndroid Build Coastguard Worker                      V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
283*4d7e907cSAndroid Build Coastguard Worker             .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
284*4d7e907cSAndroid Build Coastguard Worker             // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
285*4d7e907cSAndroid Build Coastguard Worker             // In an actual implementation provide an estimate of the synchronization uncertainty
286*4d7e907cSAndroid Build Coastguard Worker             // or don't set the field.
287*4d7e907cSAndroid Build Coastguard Worker             .timeUncertaintyNs = 1000000};
288*4d7e907cSAndroid Build Coastguard Worker 
289*4d7e907cSAndroid Build Coastguard Worker     V1_0::GnssLocation locationV1 = {
290*4d7e907cSAndroid Build Coastguard Worker             .gnssLocationFlags = 0xFF,
291*4d7e907cSAndroid Build Coastguard Worker             .latitudeDegrees = this->getLatDeg(),
292*4d7e907cSAndroid Build Coastguard Worker             .longitudeDegrees = this->getLngDeg(),
293*4d7e907cSAndroid Build Coastguard Worker             .altitudeMeters = this->getAltitudeMeters(),
294*4d7e907cSAndroid Build Coastguard Worker             .speedMetersPerSec = this->getSpeedMetersPerSec(),
295*4d7e907cSAndroid Build Coastguard Worker             .bearingDegrees = this->getBearingDegrees(),
296*4d7e907cSAndroid Build Coastguard Worker             .horizontalAccuracyMeters = this->getHorizontalAccuracyMeters(),
297*4d7e907cSAndroid Build Coastguard Worker             .verticalAccuracyMeters = this->getVerticalAccuracyMeters(),
298*4d7e907cSAndroid Build Coastguard Worker             .speedAccuracyMetersPerSecond = this->getSpeedAccuracyMetersPerSecond(),
299*4d7e907cSAndroid Build Coastguard Worker             .bearingAccuracyDegrees = this->getBearingAccuracyDegrees(),
300*4d7e907cSAndroid Build Coastguard Worker             .timestamp = this->getTimestamp()};
301*4d7e907cSAndroid Build Coastguard Worker 
302*4d7e907cSAndroid Build Coastguard Worker     V2_0::GnssLocation locationV2 = {.v1_0 = locationV1, .elapsedRealtime = currentOsTimestamp};
303*4d7e907cSAndroid Build Coastguard Worker 
304*4d7e907cSAndroid Build Coastguard Worker     return std::make_unique<V2_0::GnssLocation>(locationV2);
305*4d7e907cSAndroid Build Coastguard Worker }
306*4d7e907cSAndroid Build Coastguard Worker 
307*4d7e907cSAndroid Build Coastguard Worker }  // namespace common
308*4d7e907cSAndroid Build Coastguard Worker }  // namespace gnss
309*4d7e907cSAndroid Build Coastguard Worker }  // namespace hardware
310*4d7e907cSAndroid Build Coastguard Worker }  // namespace android