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
30 #include <LocationUtil.h>
31 #include <log_util.h>
32 #include <inttypes.h>
33
34 namespace android {
35 namespace hardware {
36 namespace gnss {
37 namespace V2_0 {
38 namespace implementation {
39
40 using ::android::hardware::gnss::V2_0::GnssLocation;
41 using ::android::hardware::gnss::V2_0::GnssConstellationType;
42 using ::android::hardware::gnss::V1_0::GnssLocationFlags;
43
convertGnssLocation(Location & in,V1_0::GnssLocation & out)44 void convertGnssLocation(Location& in, V1_0::GnssLocation& out)
45 {
46 memset(&out, 0, sizeof(V1_0::GnssLocation));
47 if (in.flags & LOCATION_HAS_LAT_LONG_BIT) {
48 out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG;
49 out.latitudeDegrees = in.latitude;
50 out.longitudeDegrees = in.longitude;
51 }
52 if (in.flags & LOCATION_HAS_ALTITUDE_BIT) {
53 out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE;
54 out.altitudeMeters = in.altitude;
55 }
56 if (in.flags & LOCATION_HAS_SPEED_BIT) {
57 out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED;
58 out.speedMetersPerSec = in.speed;
59 }
60 if (in.flags & LOCATION_HAS_BEARING_BIT) {
61 out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING;
62 out.bearingDegrees = in.bearing;
63 }
64 if (in.flags & LOCATION_HAS_ACCURACY_BIT) {
65 out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY;
66 out.horizontalAccuracyMeters = in.accuracy;
67 }
68 if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) {
69 out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY;
70 out.verticalAccuracyMeters = in.verticalAccuracy;
71 }
72 if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) {
73 out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY;
74 out.speedAccuracyMetersPerSecond = in.speedAccuracy;
75 }
76 if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) {
77 out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY;
78 out.bearingAccuracyDegrees = in.bearingAccuracy;
79 }
80
81 out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp);
82 }
83
getCurrentTime(struct timespec & currentTime,int64_t & sinceBootTimeNanos)84 bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos)
85 {
86 struct timespec sinceBootTime;
87 struct timespec sinceBootTimeTest;
88 bool clockGetTimeSuccess = false;
89 const uint32_t MAX_TIME_DELTA_VALUE_NANOS = 10000;
90 const uint32_t MAX_GET_TIME_COUNT = 20;
91 /* Attempt to get CLOCK_REALTIME and CLOCK_BOOTIME in succession without an interruption
92 or context switch (for up to MAX_GET_TIME_COUNT times) to avoid errors in the calculation */
93 for (uint32_t i = 0; i < MAX_GET_TIME_COUNT; i++) {
94 if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTime) != 0) {
95 break;
96 };
97 if (clock_gettime(CLOCK_REALTIME, ¤tTime) != 0) {
98 break;
99 }
100 if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) {
101 break;
102 };
103 sinceBootTimeNanos = sinceBootTime.tv_sec * 1000000000 + sinceBootTime.tv_nsec;
104 int64_t sinceBootTimeTestNanos =
105 sinceBootTimeTest.tv_sec * 1000000000 + sinceBootTimeTest.tv_nsec;
106 int64_t sinceBootTimeDeltaNanos = sinceBootTimeTestNanos - sinceBootTimeNanos;
107
108 /* sinceBootTime and sinceBootTimeTest should have a close value if there was no
109 interruption or context switch between clock_gettime for CLOCK_BOOTIME and
110 clock_gettime for CLOCK_REALTIME */
111 if (sinceBootTimeDeltaNanos < MAX_TIME_DELTA_VALUE_NANOS) {
112 clockGetTimeSuccess = true;
113 break;
114 } else {
115 LOC_LOGd("Delta:%" PRIi64 "ns time too large, retry number #%u...",
116 sinceBootTimeDeltaNanos, i + 1);
117 }
118 }
119 return clockGetTimeSuccess;
120 }
121
convertGnssLocation(Location & in,V2_0::GnssLocation & out)122 void convertGnssLocation(Location& in, V2_0::GnssLocation& out)
123 {
124 memset(&out, 0, sizeof(V2_0::GnssLocation));
125 convertGnssLocation(in, out.v1_0);
126
127 struct timespec currentTime;
128 int64_t sinceBootTimeNanos;
129
130 if (getCurrentTime(currentTime, sinceBootTimeNanos)) {
131 int64_t currentTimeNanos = currentTime.tv_sec*1000000000 + currentTime.tv_nsec;
132 int64_t locationTimeNanos = in.timestamp*1000000;
133 LOC_LOGD("%s]: sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 ""
134 " locationTimeNanos:%" PRIi64 "",
135 __FUNCTION__, sinceBootTimeNanos, currentTimeNanos, locationTimeNanos);
136 if (currentTimeNanos >= locationTimeNanos) {
137 int64_t ageTimeNanos = currentTimeNanos - locationTimeNanos;
138 LOC_LOGD("%s]: ageTimeNanos:%" PRIi64 ")", __FUNCTION__, ageTimeNanos);
139 // the max trusted propagation time 30s for ageTimeNanos to avoid user setting
140 //wrong time, it will affect elapsedRealtimeNanos
141 if (ageTimeNanos >= 0 && ageTimeNanos <= 30000000000) {
142 out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
143 out.elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos;
144 out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
145 // time uncertainty is the max value between abs(AP_UTC - MP_UTC) and 100ms, to
146 //verify if user change the sys time
147 out.elapsedRealtime.timeUncertaintyNs =
148 std::max((int64_t)abs(currentTimeNanos - locationTimeNanos),
149 (int64_t)100000000);
150 LOC_LOGD("%s]: timestampNs:%" PRIi64 ")",
151 __FUNCTION__, out.elapsedRealtime.timestampNs);
152 }
153 }
154 } else {
155 LOC_LOGe("Failed to calculate elapsedRealtimeNanos timestamp");
156 }
157 }
158
convertGnssLocation(const V1_0::GnssLocation & in,Location & out)159 void convertGnssLocation(const V1_0::GnssLocation& in, Location& out)
160 {
161 memset(&out, 0, sizeof(out));
162 if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) {
163 out.flags |= LOCATION_HAS_LAT_LONG_BIT;
164 out.latitude = in.latitudeDegrees;
165 out.longitude = in.longitudeDegrees;
166 }
167 if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) {
168 out.flags |= LOCATION_HAS_ALTITUDE_BIT;
169 out.altitude = in.altitudeMeters;
170 }
171 if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) {
172 out.flags |= LOCATION_HAS_SPEED_BIT;
173 out.speed = in.speedMetersPerSec;
174 }
175 if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
176 out.flags |= LOCATION_HAS_BEARING_BIT;
177 out.bearing = in.bearingDegrees;
178 }
179 if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
180 out.flags |= LOCATION_HAS_ACCURACY_BIT;
181 out.accuracy = in.horizontalAccuracyMeters;
182 }
183 if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
184 out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
185 out.verticalAccuracy = in.verticalAccuracyMeters;
186 }
187 if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
188 out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
189 out.speedAccuracy = in.speedAccuracyMetersPerSecond;
190 }
191 if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
192 out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
193 out.bearingAccuracy = in.bearingAccuracyDegrees;
194 }
195
196 out.timestamp = static_cast<uint64_t>(in.timestamp);
197 }
198
convertGnssLocation(const V2_0::GnssLocation & in,Location & out)199 void convertGnssLocation(const V2_0::GnssLocation& in, Location& out)
200 {
201 memset(&out, 0, sizeof(out));
202 convertGnssLocation(in.v1_0, out);
203 }
204
convertGnssConstellationType(GnssSvType & in,V1_0::GnssConstellationType & out)205 void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out)
206 {
207 switch(in) {
208 case GNSS_SV_TYPE_GPS:
209 out = V1_0::GnssConstellationType::GPS;
210 break;
211 case GNSS_SV_TYPE_SBAS:
212 out = V1_0::GnssConstellationType::SBAS;
213 break;
214 case GNSS_SV_TYPE_GLONASS:
215 out = V1_0::GnssConstellationType::GLONASS;
216 break;
217 case GNSS_SV_TYPE_QZSS:
218 out = V1_0::GnssConstellationType::QZSS;
219 break;
220 case GNSS_SV_TYPE_BEIDOU:
221 out = V1_0::GnssConstellationType::BEIDOU;
222 break;
223 case GNSS_SV_TYPE_GALILEO:
224 out = V1_0::GnssConstellationType::GALILEO;
225 break;
226 case GNSS_SV_TYPE_UNKNOWN:
227 default:
228 out = V1_0::GnssConstellationType::UNKNOWN;
229 break;
230 }
231 }
232
convertGnssConstellationType(GnssSvType & in,V2_0::GnssConstellationType & out)233 void convertGnssConstellationType(GnssSvType& in, V2_0::GnssConstellationType& out)
234 {
235 switch(in) {
236 case GNSS_SV_TYPE_GPS:
237 out = V2_0::GnssConstellationType::GPS;
238 break;
239 case GNSS_SV_TYPE_SBAS:
240 out = V2_0::GnssConstellationType::SBAS;
241 break;
242 case GNSS_SV_TYPE_GLONASS:
243 out = V2_0::GnssConstellationType::GLONASS;
244 break;
245 case GNSS_SV_TYPE_QZSS:
246 out = V2_0::GnssConstellationType::QZSS;
247 break;
248 case GNSS_SV_TYPE_BEIDOU:
249 out = V2_0::GnssConstellationType::BEIDOU;
250 break;
251 case GNSS_SV_TYPE_GALILEO:
252 out = V2_0::GnssConstellationType::GALILEO;
253 break;
254 case GNSS_SV_TYPE_NAVIC:
255 out = V2_0::GnssConstellationType::IRNSS;
256 break;
257 case GNSS_SV_TYPE_UNKNOWN:
258 default:
259 out = V2_0::GnssConstellationType::UNKNOWN;
260 break;
261 }
262 }
263
convertGnssEphemerisType(GnssEphemerisType & in,GnssDebug::SatelliteEphemerisType & out)264 void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
265 {
266 switch(in) {
267 case GNSS_EPH_TYPE_EPHEMERIS:
268 out = GnssDebug::SatelliteEphemerisType::EPHEMERIS;
269 break;
270 case GNSS_EPH_TYPE_ALMANAC:
271 out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY;
272 break;
273 case GNSS_EPH_TYPE_UNKNOWN:
274 default:
275 out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE;
276 break;
277 }
278 }
279
convertGnssEphemerisSource(GnssEphemerisSource & in,GnssDebug::SatelliteEphemerisSource & out)280 void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out)
281 {
282 switch(in) {
283 case GNSS_EPH_SOURCE_DEMODULATED:
284 out = GnssDebug::SatelliteEphemerisSource::DEMODULATED;
285 break;
286 case GNSS_EPH_SOURCE_SUPL_PROVIDED:
287 out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED;
288 break;
289 case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED:
290 out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED;
291 break;
292 case GNSS_EPH_SOURCE_LOCAL:
293 case GNSS_EPH_SOURCE_UNKNOWN:
294 default:
295 out = GnssDebug::SatelliteEphemerisSource::OTHER;
296 break;
297 }
298 }
299
convertGnssEphemerisHealth(GnssEphemerisHealth & in,GnssDebug::SatelliteEphemerisHealth & out)300 void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out)
301 {
302 switch(in) {
303 case GNSS_EPH_HEALTH_GOOD:
304 out = GnssDebug::SatelliteEphemerisHealth::GOOD;
305 break;
306 case GNSS_EPH_HEALTH_BAD:
307 out = GnssDebug::SatelliteEphemerisHealth::BAD;
308 break;
309 case GNSS_EPH_HEALTH_UNKNOWN:
310 default:
311 out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN;
312 break;
313 }
314 }
315
316 } // namespace implementation
317 } // namespace V2_0
318 } // namespace gnss
319 } // namespace hardware
320 } // namespace android
321