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 <gps_extended_c.h>
34 #include <loc_misc_utils.h>
35 
36 namespace android {
37 namespace hardware {
38 namespace gnss {
39 namespace V2_0 {
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 
convertGnssLocation(Location & in,V1_0::GnssLocation & out)47 void convertGnssLocation(Location& in, V1_0::GnssLocation& out)
48 {
49     memset(&out, 0, sizeof(V1_0::GnssLocation));
50     if (in.flags & LOCATION_HAS_LAT_LONG_BIT) {
51         out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG;
52         out.latitudeDegrees = in.latitude;
53         out.longitudeDegrees = in.longitude;
54     }
55     if (in.flags & LOCATION_HAS_ALTITUDE_BIT) {
56         out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE;
57         out.altitudeMeters = in.altitude;
58     }
59     if (in.flags & LOCATION_HAS_SPEED_BIT) {
60         out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED;
61         out.speedMetersPerSec = in.speed;
62     }
63     if (in.flags & LOCATION_HAS_BEARING_BIT) {
64         out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING;
65         out.bearingDegrees = in.bearing;
66     }
67     if (in.flags & LOCATION_HAS_ACCURACY_BIT) {
68         out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY;
69         out.horizontalAccuracyMeters = in.accuracy;
70     }
71     if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) {
72         out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY;
73         out.verticalAccuracyMeters = in.verticalAccuracy;
74     }
75     if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) {
76         out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY;
77         out.speedAccuracyMetersPerSecond = in.speedAccuracy;
78     }
79     if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) {
80         out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY;
81         out.bearingAccuracyDegrees = in.bearingAccuracy;
82     }
83 
84     out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp);
85 }
86 
convertGnssLocation(Location & in,V2_0::GnssLocation & out)87 void convertGnssLocation(Location& in, V2_0::GnssLocation& out)
88 {
89     memset(&out, 0, sizeof(V2_0::GnssLocation));
90     convertGnssLocation(in, out.v1_0);
91 
92     if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) {
93         out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
94         out.elapsedRealtime.timestampNs = in.elapsedRealTime;
95         out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
96         out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc;
97         LOC_LOGd("out.elapsedRealtime.timestampNs=%" PRIi64 ""
98                  " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 ""
99                  " out.elapsedRealtime.flags=0x%X",
100                  out.elapsedRealtime.timestampNs,
101                  out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags);
102     }
103 }
104 
convertGnssLocation(const V1_0::GnssLocation & in,Location & out)105 void convertGnssLocation(const V1_0::GnssLocation& in, Location& out)
106 {
107     memset(&out, 0, sizeof(out));
108     if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) {
109         out.flags |= LOCATION_HAS_LAT_LONG_BIT;
110         out.latitude = in.latitudeDegrees;
111         out.longitude = in.longitudeDegrees;
112     }
113     if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) {
114         out.flags |= LOCATION_HAS_ALTITUDE_BIT;
115         out.altitude = in.altitudeMeters;
116     }
117     if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) {
118         out.flags |= LOCATION_HAS_SPEED_BIT;
119         out.speed = in.speedMetersPerSec;
120     }
121     if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
122         out.flags |= LOCATION_HAS_BEARING_BIT;
123         out.bearing = in.bearingDegrees;
124     }
125     if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
126         out.flags |= LOCATION_HAS_ACCURACY_BIT;
127         out.accuracy = in.horizontalAccuracyMeters;
128     }
129     if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
130         out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
131         out.verticalAccuracy = in.verticalAccuracyMeters;
132     }
133     if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
134         out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
135         out.speedAccuracy = in.speedAccuracyMetersPerSecond;
136     }
137     if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
138         out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
139         out.bearingAccuracy = in.bearingAccuracyDegrees;
140     }
141 
142     out.timestamp = static_cast<uint64_t>(in.timestamp);
143 }
144 
convertGnssLocation(const V2_0::GnssLocation & in,Location & out)145 void convertGnssLocation(const V2_0::GnssLocation& in, Location& out)
146 {
147     memset(&out, 0, sizeof(out));
148     convertGnssLocation(in.v1_0, out);
149 }
150 
convertGnssConstellationType(GnssSvType & in,V1_0::GnssConstellationType & out)151 void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out)
152 {
153     switch(in) {
154         case GNSS_SV_TYPE_GPS:
155             out = V1_0::GnssConstellationType::GPS;
156             break;
157         case GNSS_SV_TYPE_SBAS:
158             out = V1_0::GnssConstellationType::SBAS;
159             break;
160         case GNSS_SV_TYPE_GLONASS:
161             out = V1_0::GnssConstellationType::GLONASS;
162             break;
163         case GNSS_SV_TYPE_QZSS:
164             out = V1_0::GnssConstellationType::QZSS;
165             break;
166         case GNSS_SV_TYPE_BEIDOU:
167             out = V1_0::GnssConstellationType::BEIDOU;
168             break;
169         case GNSS_SV_TYPE_GALILEO:
170             out = V1_0::GnssConstellationType::GALILEO;
171             break;
172         case GNSS_SV_TYPE_UNKNOWN:
173         default:
174             out = V1_0::GnssConstellationType::UNKNOWN;
175             break;
176     }
177 }
178 
convertGnssConstellationType(GnssSvType & in,V2_0::GnssConstellationType & out)179 void convertGnssConstellationType(GnssSvType& in, V2_0::GnssConstellationType& out)
180 {
181     switch(in) {
182         case GNSS_SV_TYPE_GPS:
183             out = V2_0::GnssConstellationType::GPS;
184             break;
185         case GNSS_SV_TYPE_SBAS:
186             out = V2_0::GnssConstellationType::SBAS;
187             break;
188         case GNSS_SV_TYPE_GLONASS:
189             out = V2_0::GnssConstellationType::GLONASS;
190             break;
191         case GNSS_SV_TYPE_QZSS:
192             out = V2_0::GnssConstellationType::QZSS;
193             break;
194         case GNSS_SV_TYPE_BEIDOU:
195             out = V2_0::GnssConstellationType::BEIDOU;
196             break;
197         case GNSS_SV_TYPE_GALILEO:
198             out = V2_0::GnssConstellationType::GALILEO;
199             break;
200         case GNSS_SV_TYPE_NAVIC:
201             out = V2_0::GnssConstellationType::IRNSS;
202             break;
203         case GNSS_SV_TYPE_UNKNOWN:
204         default:
205             out = V2_0::GnssConstellationType::UNKNOWN;
206             break;
207     }
208 }
209 
convertGnssSvid(GnssSv & in,int16_t & out)210 void convertGnssSvid(GnssSv& in, int16_t& out)
211 {
212     switch (in.type) {
213         case GNSS_SV_TYPE_GPS:
214             out = in.svId;
215             break;
216         case GNSS_SV_TYPE_SBAS:
217             out = in.svId;
218             break;
219         case GNSS_SV_TYPE_GLONASS:
220             if (!isGloSlotUnknown(in.svId)) { // OSN is known
221                 out = in.svId - GLO_SV_PRN_MIN + 1;
222             } else { // OSN is not known, report FCN
223                 out = in.gloFrequency + 92;
224             }
225             break;
226         case GNSS_SV_TYPE_QZSS:
227             out = in.svId;
228             break;
229         case GNSS_SV_TYPE_BEIDOU:
230             out = in.svId - BDS_SV_PRN_MIN + 1;
231             break;
232         case GNSS_SV_TYPE_GALILEO:
233             out = in.svId - GAL_SV_PRN_MIN + 1;
234             break;
235         case GNSS_SV_TYPE_NAVIC:
236             out = in.svId - NAVIC_SV_PRN_MIN + 1;
237             break;
238         default:
239             out = in.svId;
240             break;
241     }
242 }
243 
convertGnssSvid(GnssMeasurementsData & in,int16_t & out)244 void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
245 {
246     switch (in.svType) {
247         case GNSS_SV_TYPE_GPS:
248             out = in.svId;
249             break;
250         case GNSS_SV_TYPE_SBAS:
251             out = in.svId;
252             break;
253         case GNSS_SV_TYPE_GLONASS:
254             if (!isGloSlotUnknown(in.svId)) { // OSN is known
255                 out = in.svId - GLO_SV_PRN_MIN + 1;
256             } else { // OSN is not known, report FCN
257                 out = in.gloFrequency + 92;
258             }
259             break;
260         case GNSS_SV_TYPE_QZSS:
261             out = in.svId;
262             break;
263         case GNSS_SV_TYPE_BEIDOU:
264             out = in.svId - BDS_SV_PRN_MIN + 1;
265             break;
266         case GNSS_SV_TYPE_GALILEO:
267             out = in.svId - GAL_SV_PRN_MIN + 1;
268             break;
269         case GNSS_SV_TYPE_NAVIC:
270             out = in.svId - NAVIC_SV_PRN_MIN + 1;
271             break;
272         default:
273             out = in.svId;
274             break;
275     }
276 }
277 
convertGnssEphemerisType(GnssEphemerisType & in,GnssDebug::SatelliteEphemerisType & out)278 void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
279 {
280     switch(in) {
281         case GNSS_EPH_TYPE_EPHEMERIS:
282             out = GnssDebug::SatelliteEphemerisType::EPHEMERIS;
283             break;
284         case GNSS_EPH_TYPE_ALMANAC:
285             out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY;
286             break;
287         case GNSS_EPH_TYPE_UNKNOWN:
288         default:
289             out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE;
290             break;
291     }
292 }
293 
convertGnssEphemerisSource(GnssEphemerisSource & in,GnssDebug::SatelliteEphemerisSource & out)294 void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out)
295 {
296     switch(in) {
297         case GNSS_EPH_SOURCE_DEMODULATED:
298             out = GnssDebug::SatelliteEphemerisSource::DEMODULATED;
299             break;
300         case GNSS_EPH_SOURCE_SUPL_PROVIDED:
301             out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED;
302             break;
303         case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED:
304             out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED;
305             break;
306         case GNSS_EPH_SOURCE_LOCAL:
307         case GNSS_EPH_SOURCE_UNKNOWN:
308         default:
309             out = GnssDebug::SatelliteEphemerisSource::OTHER;
310             break;
311     }
312 }
313 
convertGnssEphemerisHealth(GnssEphemerisHealth & in,GnssDebug::SatelliteEphemerisHealth & out)314 void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out)
315 {
316     switch(in) {
317         case GNSS_EPH_HEALTH_GOOD:
318             out = GnssDebug::SatelliteEphemerisHealth::GOOD;
319             break;
320         case GNSS_EPH_HEALTH_BAD:
321             out = GnssDebug::SatelliteEphemerisHealth::BAD;
322             break;
323         case GNSS_EPH_HEALTH_UNKNOWN:
324         default:
325             out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN;
326             break;
327     }
328 }
329 
330 }  // namespace implementation
331 }  // namespace V2_0
332 }  // namespace gnss
333 }  // namespace hardware
334 }  // namespace android
335