1 /* Copyright (c) 2017-2020, 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
30 #include <LocationUtil.h>
31 #include <log_util.h>
32 #include <inttypes.h>
33 #include <loc_misc_utils.h>
34 #include <gps_extended_c.h>
35
36 namespace android {
37 namespace hardware {
38 namespace gnss {
39 namespace V2_1 {
40 namespace implementation {
41
42 using ::android::hardware::gnss::V2_0::GnssLocation;
43 using ::android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
44 using ::android::hardware::gnss::V2_0::GnssConstellationType;
45 using ::android::hardware::gnss::V1_0::GnssLocationFlags;
46 using ::android::hardware::gnss::measurement_corrections::V1_0::GnssSingleSatCorrectionFlags;
47
convertGnssLocation(Location & in,V1_0::GnssLocation & out)48 void convertGnssLocation(Location& in, V1_0::GnssLocation& out)
49 {
50 memset(&out, 0, sizeof(V1_0::GnssLocation));
51 if (in.flags & LOCATION_HAS_LAT_LONG_BIT) {
52 out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG;
53 out.latitudeDegrees = in.latitude;
54 out.longitudeDegrees = in.longitude;
55 }
56 if (in.flags & LOCATION_HAS_ALTITUDE_BIT) {
57 out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE;
58 out.altitudeMeters = in.altitude;
59 }
60 if (in.flags & LOCATION_HAS_SPEED_BIT) {
61 out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED;
62 out.speedMetersPerSec = in.speed;
63 }
64 if (in.flags & LOCATION_HAS_BEARING_BIT) {
65 out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING;
66 out.bearingDegrees = in.bearing;
67 }
68 if (in.flags & LOCATION_HAS_ACCURACY_BIT) {
69 out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY;
70 out.horizontalAccuracyMeters = in.accuracy;
71 }
72 if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) {
73 out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY;
74 out.verticalAccuracyMeters = in.verticalAccuracy;
75 }
76 if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) {
77 out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY;
78 out.speedAccuracyMetersPerSecond = in.speedAccuracy;
79 }
80 if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) {
81 out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY;
82 out.bearingAccuracyDegrees = in.bearingAccuracy;
83 }
84
85 out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp);
86 }
87
getCurrentTime(struct timespec & currentTime,int64_t & sinceBootTimeNanos)88 bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos)
89 {
90 struct timespec sinceBootTime;
91 struct timespec sinceBootTimeTest;
92 bool clockGetTimeSuccess = false;
93 const uint32_t MAX_TIME_DELTA_VALUE_NANOS = 10000;
94 const uint32_t MAX_GET_TIME_COUNT = 20;
95 /* Attempt to get CLOCK_REALTIME and CLOCK_BOOTIME in succession without an interruption
96 or context switch (for up to MAX_GET_TIME_COUNT times) to avoid errors in the calculation */
97 for (uint32_t i = 0; i < MAX_GET_TIME_COUNT; i++) {
98 if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTime) != 0) {
99 break;
100 };
101 if (clock_gettime(CLOCK_REALTIME, ¤tTime) != 0) {
102 break;
103 }
104 if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) {
105 break;
106 };
107 sinceBootTimeNanos = sinceBootTime.tv_sec * 1000000000 + sinceBootTime.tv_nsec;
108 int64_t sinceBootTimeTestNanos =
109 sinceBootTimeTest.tv_sec * 1000000000 + sinceBootTimeTest.tv_nsec;
110 int64_t sinceBootTimeDeltaNanos = sinceBootTimeTestNanos - sinceBootTimeNanos;
111
112 /* sinceBootTime and sinceBootTimeTest should have a close value if there was no
113 interruption or context switch between clock_gettime for CLOCK_BOOTIME and
114 clock_gettime for CLOCK_REALTIME */
115 if (sinceBootTimeDeltaNanos < MAX_TIME_DELTA_VALUE_NANOS) {
116 clockGetTimeSuccess = true;
117 break;
118 } else {
119 LOC_LOGd("Delta:%" PRIi64 "ns time too large, retry number #%u...",
120 sinceBootTimeDeltaNanos, i + 1);
121 }
122 }
123 return clockGetTimeSuccess;
124 }
125
convertGnssLocation(Location & in,V2_0::GnssLocation & out)126 void convertGnssLocation(Location& in, V2_0::GnssLocation& out)
127 {
128 memset(&out, 0, sizeof(V2_0::GnssLocation));
129 convertGnssLocation(in, out.v1_0);
130
131 struct timespec currentTime;
132 int64_t sinceBootTimeNanos;
133
134 if (getCurrentTime(currentTime, sinceBootTimeNanos)) {
135 if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) {
136 uint64_t qtimerDiff = 0;
137 uint64_t qTimerTickCount = getQTimerTickCount();
138 if (qTimerTickCount >= in.elapsedRealTime) {
139 qtimerDiff = qTimerTickCount - in.elapsedRealTime;
140 }
141 LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " in.elapsedRealTime=%" PRIi64 ""
142 " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "",
143 sinceBootTimeNanos, in.elapsedRealTime, qTimerTickCount, qtimerDiff);
144 uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff));
145 if (sinceBootTimeNanos >= qTimerDiffNanos) {
146 out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
147 out.elapsedRealtime.timestampNs = sinceBootTimeNanos - qTimerDiffNanos;
148 out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
149 out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc;
150 }
151 } else {
152 int64_t currentTimeNanos = currentTime.tv_sec*1000000000 + currentTime.tv_nsec;
153 int64_t locationTimeNanos = in.timestamp*1000000;
154 LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 ""
155 " locationTimeNanos:%" PRIi64 "",
156 sinceBootTimeNanos, currentTimeNanos, locationTimeNanos);
157 if (currentTimeNanos >= locationTimeNanos) {
158 int64_t ageTimeNanos = currentTimeNanos - locationTimeNanos;
159 LOC_LOGv("ageTimeNanos:%" PRIi64 ")", ageTimeNanos);
160 // the max trusted propagation time 100ms for ageTimeNanos to avoid user setting
161 // wrong time, it will affect elapsedRealtimeNanos
162 if (ageTimeNanos <= 100000000) {
163 out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
164 out.elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos;
165 out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
166 // time uncertainty is the max value between abs(AP_UTC - MP_UTC) and 100ms, to
167 // verify if user change the sys time
168 out.elapsedRealtime.timeUncertaintyNs =
169 std::max(ageTimeNanos, (int64_t)100000000);
170 }
171 }
172 }
173 }
174 LOC_LOGv("out.elapsedRealtime.timestampNs=%" PRIi64 ""
175 " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 ""
176 " out.elapsedRealtime.flags=0x%X",
177 out.elapsedRealtime.timestampNs,
178 out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags);
179 }
180
convertGnssLocation(const V1_0::GnssLocation & in,Location & out)181 void convertGnssLocation(const V1_0::GnssLocation& in, Location& out)
182 {
183 memset(&out, 0, sizeof(out));
184 if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) {
185 out.flags |= LOCATION_HAS_LAT_LONG_BIT;
186 out.latitude = in.latitudeDegrees;
187 out.longitude = in.longitudeDegrees;
188 }
189 if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) {
190 out.flags |= LOCATION_HAS_ALTITUDE_BIT;
191 out.altitude = in.altitudeMeters;
192 }
193 if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) {
194 out.flags |= LOCATION_HAS_SPEED_BIT;
195 out.speed = in.speedMetersPerSec;
196 }
197 if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
198 out.flags |= LOCATION_HAS_BEARING_BIT;
199 out.bearing = in.bearingDegrees;
200 }
201 if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
202 out.flags |= LOCATION_HAS_ACCURACY_BIT;
203 out.accuracy = in.horizontalAccuracyMeters;
204 }
205 if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
206 out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
207 out.verticalAccuracy = in.verticalAccuracyMeters;
208 }
209 if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
210 out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
211 out.speedAccuracy = in.speedAccuracyMetersPerSecond;
212 }
213 if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
214 out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
215 out.bearingAccuracy = in.bearingAccuracyDegrees;
216 }
217
218 out.timestamp = static_cast<uint64_t>(in.timestamp);
219 }
220
convertGnssLocation(const V2_0::GnssLocation & in,Location & out)221 void convertGnssLocation(const V2_0::GnssLocation& in, Location& out)
222 {
223 memset(&out, 0, sizeof(out));
224 convertGnssLocation(in.v1_0, out);
225 }
226
convertGnssConstellationType(GnssSvType & in,V1_0::GnssConstellationType & out)227 void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out)
228 {
229 switch(in) {
230 case GNSS_SV_TYPE_GPS:
231 out = V1_0::GnssConstellationType::GPS;
232 break;
233 case GNSS_SV_TYPE_SBAS:
234 out = V1_0::GnssConstellationType::SBAS;
235 break;
236 case GNSS_SV_TYPE_GLONASS:
237 out = V1_0::GnssConstellationType::GLONASS;
238 break;
239 case GNSS_SV_TYPE_QZSS:
240 out = V1_0::GnssConstellationType::QZSS;
241 break;
242 case GNSS_SV_TYPE_BEIDOU:
243 out = V1_0::GnssConstellationType::BEIDOU;
244 break;
245 case GNSS_SV_TYPE_GALILEO:
246 out = V1_0::GnssConstellationType::GALILEO;
247 break;
248 case GNSS_SV_TYPE_UNKNOWN:
249 default:
250 out = V1_0::GnssConstellationType::UNKNOWN;
251 break;
252 }
253 }
254
convertGnssConstellationType(GnssSvType & in,V2_0::GnssConstellationType & out)255 void convertGnssConstellationType(GnssSvType& in, V2_0::GnssConstellationType& out)
256 {
257 switch(in) {
258 case GNSS_SV_TYPE_GPS:
259 out = V2_0::GnssConstellationType::GPS;
260 break;
261 case GNSS_SV_TYPE_SBAS:
262 out = V2_0::GnssConstellationType::SBAS;
263 break;
264 case GNSS_SV_TYPE_GLONASS:
265 out = V2_0::GnssConstellationType::GLONASS;
266 break;
267 case GNSS_SV_TYPE_QZSS:
268 out = V2_0::GnssConstellationType::QZSS;
269 break;
270 case GNSS_SV_TYPE_BEIDOU:
271 out = V2_0::GnssConstellationType::BEIDOU;
272 break;
273 case GNSS_SV_TYPE_GALILEO:
274 out = V2_0::GnssConstellationType::GALILEO;
275 break;
276 case GNSS_SV_TYPE_NAVIC:
277 out = V2_0::GnssConstellationType::IRNSS;
278 break;
279 case GNSS_SV_TYPE_UNKNOWN:
280 default:
281 out = V2_0::GnssConstellationType::UNKNOWN;
282 break;
283 }
284 }
285
convertGnssSvid(GnssSv & in,int16_t & out)286 void convertGnssSvid(GnssSv& in, int16_t& out)
287 {
288 switch (in.type) {
289 case GNSS_SV_TYPE_GPS:
290 out = in.svId;
291 break;
292 case GNSS_SV_TYPE_SBAS:
293 out = in.svId;
294 break;
295 case GNSS_SV_TYPE_GLONASS:
296 out = in.svId - GLO_SV_PRN_MIN + 1;
297 break;
298 case GNSS_SV_TYPE_QZSS:
299 out = in.svId;
300 break;
301 case GNSS_SV_TYPE_BEIDOU:
302 out = in.svId - BDS_SV_PRN_MIN + 1;
303 break;
304 case GNSS_SV_TYPE_GALILEO:
305 out = in.svId - GAL_SV_PRN_MIN + 1;
306 break;
307 case GNSS_SV_TYPE_NAVIC:
308 /*Android doesn't define Navic svid range yet, use Naviv svid [1, 14] now
309 will update this once Android give Navic svid definiitons */
310 out = in.svId - NAVIC_SV_PRN_MIN + 1;
311 break;
312 default:
313 out = in.svId;
314 break;
315 }
316 }
317
convertGnssSvid(GnssMeasurementsData & in,int16_t & out)318 void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
319 {
320 switch (in.svType) {
321 case GNSS_SV_TYPE_GPS:
322 out = in.svId;
323 break;
324 case GNSS_SV_TYPE_SBAS:
325 out = in.svId;
326 break;
327 case GNSS_SV_TYPE_GLONASS:
328 if (in.svId != 255) { // OSN is known
329 out = in.svId - GLO_SV_PRN_MIN + 1;
330 } else { // OSN is not known, report FCN
331 out = in.gloFrequency + 92;
332 }
333 break;
334 case GNSS_SV_TYPE_QZSS:
335 out = in.svId;
336 break;
337 case GNSS_SV_TYPE_BEIDOU:
338 out = in.svId - BDS_SV_PRN_MIN + 1;
339 break;
340 case GNSS_SV_TYPE_GALILEO:
341 out = in.svId - GAL_SV_PRN_MIN + 1;
342 break;
343 case GNSS_SV_TYPE_NAVIC:
344 /*Android doesn't define Navic svid range yet, use Naviv svid [1, 14] now
345 will update this once Android give Navic svid definiitons */
346 out = in.svId - NAVIC_SV_PRN_MIN + 1;
347 break;
348 default:
349 out = in.svId;
350 break;
351 }
352 }
353
convertGnssEphemerisType(GnssEphemerisType & in,GnssDebug::SatelliteEphemerisType & out)354 void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
355 {
356 switch(in) {
357 case GNSS_EPH_TYPE_EPHEMERIS:
358 out = GnssDebug::SatelliteEphemerisType::EPHEMERIS;
359 break;
360 case GNSS_EPH_TYPE_ALMANAC:
361 out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY;
362 break;
363 case GNSS_EPH_TYPE_UNKNOWN:
364 default:
365 out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE;
366 break;
367 }
368 }
369
convertGnssEphemerisSource(GnssEphemerisSource & in,GnssDebug::SatelliteEphemerisSource & out)370 void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out)
371 {
372 switch(in) {
373 case GNSS_EPH_SOURCE_DEMODULATED:
374 out = GnssDebug::SatelliteEphemerisSource::DEMODULATED;
375 break;
376 case GNSS_EPH_SOURCE_SUPL_PROVIDED:
377 out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED;
378 break;
379 case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED:
380 out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED;
381 break;
382 case GNSS_EPH_SOURCE_LOCAL:
383 case GNSS_EPH_SOURCE_UNKNOWN:
384 default:
385 out = GnssDebug::SatelliteEphemerisSource::OTHER;
386 break;
387 }
388 }
389
convertGnssEphemerisHealth(GnssEphemerisHealth & in,GnssDebug::SatelliteEphemerisHealth & out)390 void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out)
391 {
392 switch(in) {
393 case GNSS_EPH_HEALTH_GOOD:
394 out = GnssDebug::SatelliteEphemerisHealth::GOOD;
395 break;
396 case GNSS_EPH_HEALTH_BAD:
397 out = GnssDebug::SatelliteEphemerisHealth::BAD;
398 break;
399 case GNSS_EPH_HEALTH_UNKNOWN:
400 default:
401 out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN;
402 break;
403 }
404 }
405
convertSingleSatCorrections(const SingleSatCorrection & in,GnssSingleSatCorrection & out)406 void convertSingleSatCorrections(const SingleSatCorrection& in, GnssSingleSatCorrection& out)
407 {
408 out.flags = GNSS_MEAS_CORR_UNKNOWN_BIT;
409 if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_SAT_IS_LOS_PROBABILITY)) {
410 out.flags |= GNSS_MEAS_CORR_HAS_SAT_IS_LOS_PROBABILITY_BIT;
411 }
412 if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH)) {
413 out.flags |= GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_BIT;
414 }
415 if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH_UNC)) {
416 out.flags |= GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_UNC_BIT;
417 }
418 if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE)) {
419 out.flags |= GNSS_MEAS_CORR_HAS_REFLECTING_PLANE_BIT;
420 }
421 switch (in.constellation) {
422 case (::android::hardware::gnss::V1_0::GnssConstellationType::GPS):
423 out.svType = GNSS_SV_TYPE_GPS;
424 break;
425 case (::android::hardware::gnss::V1_0::GnssConstellationType::SBAS):
426 out.svType = GNSS_SV_TYPE_SBAS;
427 break;
428 case (::android::hardware::gnss::V1_0::GnssConstellationType::GLONASS):
429 out.svType = GNSS_SV_TYPE_GLONASS;
430 break;
431 case (::android::hardware::gnss::V1_0::GnssConstellationType::QZSS):
432 out.svType = GNSS_SV_TYPE_QZSS;
433 break;
434 case (::android::hardware::gnss::V1_0::GnssConstellationType::BEIDOU):
435 out.svType = GNSS_SV_TYPE_BEIDOU;
436 break;
437 case (::android::hardware::gnss::V1_0::GnssConstellationType::GALILEO):
438 out.svType = GNSS_SV_TYPE_GALILEO;
439 break;
440 case (::android::hardware::gnss::V1_0::GnssConstellationType::UNKNOWN):
441 default:
442 out.svType = GNSS_SV_TYPE_UNKNOWN;
443 break;
444 }
445 out.svId = in.svid;
446 out.carrierFrequencyHz = in.carrierFrequencyHz;
447 out.probSatIsLos = in.probSatIsLos;
448 out.excessPathLengthMeters = in.excessPathLengthMeters;
449 out.excessPathLengthUncertaintyMeters = in.excessPathLengthUncertaintyMeters;
450
451 out.reflectingPlane.latitudeDegrees = in.reflectingPlane.latitudeDegrees;
452 out.reflectingPlane.longitudeDegrees = in.reflectingPlane.longitudeDegrees;
453 out.reflectingPlane.altitudeMeters = in.reflectingPlane.altitudeMeters;
454 out.reflectingPlane.azimuthDegrees = in.reflectingPlane.azimuthDegrees;
455 }
456
convertMeasurementCorrections(const MeasurementCorrectionsV1_0 & in,GnssMeasurementCorrections & out)457 void convertMeasurementCorrections(const MeasurementCorrectionsV1_0& in,
458 GnssMeasurementCorrections& out)
459 {
460 memset(&out, 0, sizeof(GnssMeasurementCorrections));
461 out.latitudeDegrees = in.latitudeDegrees;
462 out.longitudeDegrees = in.longitudeDegrees;
463 out.altitudeMeters = in.altitudeMeters;
464 out.horizontalPositionUncertaintyMeters = in.horizontalPositionUncertaintyMeters;
465 out.verticalPositionUncertaintyMeters = in.verticalPositionUncertaintyMeters;
466 out.toaGpsNanosecondsOfWeek = in.toaGpsNanosecondsOfWeek;
467
468 for (int i = 0; i < in.satCorrections.size(); i++) {
469 GnssSingleSatCorrection gnssSingleSatCorrection;
470
471 convertSingleSatCorrections(in.satCorrections[i], gnssSingleSatCorrection);
472 out.satCorrections.push_back(gnssSingleSatCorrection);
473 }
474 }
475
476 } // namespace implementation
477 } // namespace V2_1
478 } // namespace gnss
479 } // namespace hardware
480 } // namespace android
481