1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "GnssRawMeasurementParser.h"
18 
19 namespace android {
20 namespace hardware {
21 namespace gnss {
22 namespace common {
23 
24 using aidl::android::hardware::gnss::ElapsedRealtime;
25 using aidl::android::hardware::gnss::GnssClock;
26 using aidl::android::hardware::gnss::GnssConstellationType;
27 using aidl::android::hardware::gnss::GnssData;
28 using aidl::android::hardware::gnss::GnssMeasurement;
29 using aidl::android::hardware::gnss::GnssMultipathIndicator;
30 using aidl::android::hardware::gnss::GnssSignalType;
31 
32 using ParseUtils = ::android::hardware::gnss::common::ParseUtils;
33 
getColumnIdNameMappingFromHeader(const std::string & header)34 std::unordered_map<std::string, int> GnssRawMeasurementParser::getColumnIdNameMappingFromHeader(
35         const std::string& header) {
36     std::vector<std::string> columnNames;
37     std::unordered_map<std::string, int> columnNameIdMapping;
38     std::string s = header;
39     // Trim left spaces
40     s.erase(s.begin(),
41             std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
42     // Trim right spaces
43     s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); })
44                     .base(),
45             s.end());
46     // Remove comment symbol, start from `Raw`.
47     s = s.substr(s.find("Raw"));
48 
49     ParseUtils::splitStr(s, COMMA_SEPARATOR, columnNames);
50     int columnId = 0;
51     for (auto& name : columnNames) {
52         columnNameIdMapping[name] = columnId++;
53     }
54 
55     return columnNameIdMapping;
56 }
57 
getClockFlags(const std::vector<std::string> & rawMeasurementRecordValues,const std::unordered_map<std::string,int> & columnNameIdMapping)58 int GnssRawMeasurementParser::getClockFlags(
59         const std::vector<std::string>& rawMeasurementRecordValues,
60         const std::unordered_map<std::string, int>& columnNameIdMapping) {
61     int clockFlags = 0;
62     if (!rawMeasurementRecordValues[columnNameIdMapping.at("LeapSecond")].empty()) {
63         clockFlags |= GnssClock::HAS_LEAP_SECOND;
64     }
65     if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullBiasNanos")].empty()) {
66         clockFlags |= GnssClock::HAS_FULL_BIAS;
67     }
68     if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasNanos")].empty()) {
69         clockFlags |= GnssClock::HAS_BIAS;
70     }
71     if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")].empty()) {
72         clockFlags |= GnssClock::HAS_BIAS_UNCERTAINTY;
73     }
74     if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")].empty()) {
75         clockFlags |= GnssClock::HAS_DRIFT;
76     }
77     if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftUncertaintyNanosPerSecond")]
78                  .empty()) {
79         clockFlags |= GnssClock::HAS_DRIFT_UNCERTAINTY;
80     }
81     return clockFlags;
82 }
83 
getElapsedRealtimeFlags(const std::vector<std::string> & rawMeasurementRecordValues,const std::unordered_map<std::string,int> & columnNameIdMapping)84 int GnssRawMeasurementParser::getElapsedRealtimeFlags(
85         const std::vector<std::string>& rawMeasurementRecordValues,
86         const std::unordered_map<std::string, int>& columnNameIdMapping) {
87     int elapsedRealtimeFlags = ElapsedRealtime::HAS_TIMESTAMP_NS;
88     if (!rawMeasurementRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")].empty()) {
89         elapsedRealtimeFlags |= ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS;
90     }
91     return elapsedRealtimeFlags;
92 }
93 
getRawMeasurementFlags(const std::vector<std::string> & rawMeasurementRecordValues,const std::unordered_map<std::string,int> & columnNameIdMapping)94 int GnssRawMeasurementParser::getRawMeasurementFlags(
95         const std::vector<std::string>& rawMeasurementRecordValues,
96         const std::unordered_map<std::string, int>& columnNameIdMapping) {
97     int rawMeasurementFlags = 0;
98     if (!rawMeasurementRecordValues[columnNameIdMapping.at("SnrInDb")].empty()) {
99         rawMeasurementFlags |= GnssMeasurement::HAS_SNR;
100     }
101     if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierFrequencyHz")].empty()) {
102         rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_FREQUENCY;
103     }
104     if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierCycles")].empty()) {
105         rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_CYCLES;
106     }
107     if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhase")].empty()) {
108         rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE;
109     }
110     if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhaseUncertainty")].empty()) {
111         rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY;
112     }
113     if (!rawMeasurementRecordValues[columnNameIdMapping.at("AgcDb")].empty()) {
114         rawMeasurementFlags |= GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL;
115     }
116     if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasNanos")].empty()) {
117         rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB;
118     }
119     if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasUncertaintyNanos")]
120                  .empty()) {
121         rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY;
122     }
123     if (!rawMeasurementRecordValues[columnNameIdMapping.at("SatelliteInterSignalBiasNanos")]
124                  .empty()) {
125         rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB;
126     }
127     if (!rawMeasurementRecordValues[columnNameIdMapping.at(
128                                             "SatelliteInterSignalBiasUncertaintyNanos")]
129                  .empty()) {
130         rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY;
131     }
132     // HAS_SATELLITE_PVT and HAS_CORRELATION_VECTOR fields currently not in rawmeasurement
133     // output, need add them later.
134     return rawMeasurementFlags;
135 }
136 
getGnssConstellationType(int constellationType)137 GnssConstellationType GnssRawMeasurementParser::getGnssConstellationType(int constellationType) {
138     GnssConstellationType gnssConstellationType =
139             aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
140 
141     switch (constellationType) {
142         case 1:
143             gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GPS;
144             break;
145         case 2:
146             gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::SBAS;
147             break;
148         case 3:
149             gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GLONASS;
150             break;
151         case 4:
152             gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::QZSS;
153             break;
154         case 5:
155             gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::BEIDOU;
156             break;
157         case 6:
158             gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GALILEO;
159             break;
160         default:
161             gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
162     }
163 
164     return gnssConstellationType;
165 }
166 
getMeasurementFromStrs(std::string & rawMeasurementStr)167 std::unique_ptr<GnssData> GnssRawMeasurementParser::getMeasurementFromStrs(
168         std::string& rawMeasurementStr) {
169     /*
170      * Raw,utcTimeMillis,TimeNanos,LeapSecond,TimeUncertaintyNanos,FullBiasNanos,BiasNanos,
171      * BiasUncertaintyNanos,DriftNanosPerSecond,DriftUncertaintyNanosPerSecond,
172      * HardwareClockDiscontinuityCount,Svid,TimeOffsetNanos,State,ReceivedSvTimeNanos,
173      * ReceivedSvTimeUncertaintyNanos,Cn0DbHz,PseudorangeRateMetersPerSecond,
174      * PseudorangeRateUncertaintyMetersPerSecond,AccumulatedDeltaRangeState,
175      * AccumulatedDeltaRangeMeters,AccumulatedDeltaRangeUncertaintyMeters,CarrierFrequencyHz,
176      * CarrierCycles,CarrierPhase,CarrierPhaseUncertainty,MultipathIndicator,SnrInDb,
177      * ConstellationType,AgcDb,BasebandCn0DbHz,FullInterSignalBiasNanos,
178      * FullInterSignalBiasUncertaintyNanos,SatelliteInterSignalBiasNanos,
179      * SatelliteInterSignalBiasUncertaintyNanos,CodeType,ChipsetElapsedRealtimeNanos
180      */
181     ALOGD("Parsing %zu bytes rawMeasurementStr.", rawMeasurementStr.size());
182     if (rawMeasurementStr.empty()) {
183         return nullptr;
184     }
185     std::vector<std::string> rawMeasurementStrRecords;
186     ParseUtils::splitStr(rawMeasurementStr, LINE_SEPARATOR, rawMeasurementStrRecords);
187     if (rawMeasurementStrRecords.size() <= 1) {
188         ALOGE("Raw GNSS Measurements parser failed. (No records) ");
189         return nullptr;
190     }
191 
192     // Get the column name mapping from the header.
193     std::unordered_map<std::string, int> columnNameIdMapping =
194             getColumnIdNameMappingFromHeader(rawMeasurementStrRecords[0]);
195 
196     if (columnNameIdMapping.size() < 37 || !ParseUtils::isValidHeader(columnNameIdMapping)) {
197         ALOGE("Raw GNSS Measurements parser failed. (No header or missing columns.) ");
198         return nullptr;
199     }
200 
201     // Set GnssClock from 1st record.
202     std::size_t pointer = 1;
203     std::vector<std::string> firstRecordValues;
204     ParseUtils::splitStr(rawMeasurementStrRecords[pointer], COMMA_SEPARATOR, firstRecordValues);
205     GnssClock clock = {
206             .gnssClockFlags = getClockFlags(firstRecordValues, columnNameIdMapping),
207             .timeNs = ParseUtils::tryParseLongLong(
208                     firstRecordValues[columnNameIdMapping.at("TimeNanos")], 0),
209             .fullBiasNs = ParseUtils::tryParseLongLong(
210                     firstRecordValues[columnNameIdMapping.at("FullBiasNanos")], 0),
211             .biasNs = ParseUtils::tryParseDouble(
212                     firstRecordValues[columnNameIdMapping.at("BiasNanos")], 0),
213             .biasUncertaintyNs = ParseUtils::tryParseDouble(
214                     firstRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")], 0),
215             .driftNsps = ParseUtils::tryParseDouble(
216                     firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
217             .driftUncertaintyNsps = ParseUtils::tryParseDouble(
218                     firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
219             .hwClockDiscontinuityCount = ParseUtils::tryParseInt(
220                     firstRecordValues[columnNameIdMapping.at("HardwareClockDiscontinuityCount")],
221                     0)};
222 
223     ElapsedRealtime timestamp = {
224             .flags = getElapsedRealtimeFlags(firstRecordValues, columnNameIdMapping),
225             .timestampNs = ParseUtils::tryParseLongLong(
226                     firstRecordValues[columnNameIdMapping.at("ChipsetElapsedRealtimeNanos")]),
227             .timeUncertaintyNs = ParseUtils::tryParseDouble(
228                     firstRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")], 0)};
229 
230     std::vector<GnssMeasurement> measurementsVec;
231     for (pointer = 1; pointer < rawMeasurementStrRecords.size(); pointer++) {
232         std::vector<std::string> rawMeasurementValues;
233         std::string line = rawMeasurementStrRecords[pointer];
234         ParseUtils::splitStr(line, COMMA_SEPARATOR, rawMeasurementValues);
235         GnssSignalType signalType = {
236                 .constellation = getGnssConstellationType(ParseUtils::tryParseInt(
237                         rawMeasurementValues[columnNameIdMapping.at("ConstellationType")], 0)),
238                 .carrierFrequencyHz = ParseUtils::tryParseDouble(
239                         rawMeasurementValues[columnNameIdMapping.at("CarrierFrequencyHz")], 0),
240                 .codeType = rawMeasurementValues[columnNameIdMapping.at("CodeType")],
241         };
242         GnssMeasurement measurement = {
243                 .flags = getRawMeasurementFlags(rawMeasurementValues, columnNameIdMapping),
244                 .svid = ParseUtils::tryParseInt(
245                         rawMeasurementValues[columnNameIdMapping.at("Svid")], 0),
246                 .signalType = signalType,
247                 .receivedSvTimeInNs = ParseUtils::tryParseLongLong(
248                         rawMeasurementValues[columnNameIdMapping.at("ReceivedSvTimeNanos")], 0),
249                 .receivedSvTimeUncertaintyInNs =
250                         ParseUtils::tryParseLongLong(rawMeasurementValues[columnNameIdMapping.at(
251                                                              "ReceivedSvTimeUncertaintyNanos")],
252                                                      0),
253                 .antennaCN0DbHz = ParseUtils::tryParseDouble(
254                         rawMeasurementValues[columnNameIdMapping.at("Cn0DbHz")], 0),
255                 .basebandCN0DbHz = ParseUtils::tryParseDouble(
256                         rawMeasurementValues[columnNameIdMapping.at("BasebandCn0DbHz")], 0),
257                 .agcLevelDb = ParseUtils::tryParseDouble(
258                         rawMeasurementValues[columnNameIdMapping.at("AgcDb")], 0),
259                 .pseudorangeRateMps =
260                         ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
261                                                            "PseudorangeRateMetersPerSecond")],
262                                                    0),
263                 .pseudorangeRateUncertaintyMps = ParseUtils::tryParseDouble(
264                         rawMeasurementValues[columnNameIdMapping.at(
265                                 "PseudorangeRateUncertaintyMetersPerSecond")],
266                         0),
267                 .accumulatedDeltaRangeState = ParseUtils::tryParseInt(
268                         rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeState")],
269                         0),
270                 .accumulatedDeltaRangeM = ParseUtils::tryParseDouble(
271                         rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeMeters")],
272                         0),
273                 .accumulatedDeltaRangeUncertaintyM = ParseUtils::tryParseDouble(
274                         rawMeasurementValues[columnNameIdMapping.at(
275                                 "AccumulatedDeltaRangeUncertaintyMeters")],
276                         0),
277                 .multipathIndicator = GnssMultipathIndicator::UNKNOWN,  // Not in GnssLogger yet.
278                 .state = ParseUtils::tryParseInt(
279                         rawMeasurementValues[columnNameIdMapping.at("State")], 0),
280                 .fullInterSignalBiasNs = ParseUtils::tryParseDouble(rawMeasurementValues[31], 0),
281                 .fullInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
282                         rawMeasurementValues[columnNameIdMapping.at("FullInterSignalBiasNanos")],
283                         0),
284                 .satelliteInterSignalBiasNs =
285                         ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
286                                                            "SatelliteInterSignalBiasNanos")],
287                                                    0),
288                 .satelliteInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
289                         rawMeasurementValues[columnNameIdMapping.at(
290                                 "SatelliteInterSignalBiasUncertaintyNanos")],
291                         0),
292                 .satellitePvt = {},
293                 .correlationVectors = {}};
294         measurementsVec.push_back(measurement);
295     }
296 
297     GnssData gnssData = {
298             .measurements = measurementsVec, .clock = clock, .elapsedRealtime = timestamp};
299     return std::make_unique<GnssData>(gnssData);
300 }
301 
302 }  // namespace common
303 }  // namespace gnss
304 }  // namespace hardware
305 }  // namespace android
306