1 /* Copyright (c) 2017, 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 #define LOG_TAG "LocSvc_GnssAdapter"
30
31 #include <sys/stat.h>
32 #include <errno.h>
33 #include <ctype.h>
34 #include <cutils/properties.h>
35 #include <math.h>
36 #include <arpa/inet.h>
37 #include <netinet/in.h>
38 #include <netdb.h>
39 #include <GnssAdapter.h>
40 #include <string>
41 #include <loc_log.h>
42 #include <loc_nmea.h>
43 #include <Agps.h>
44 #include <SystemStatus.h>
45
46 #include <loc_nmea.h>
47 #include <vector>
48 #include <string>
49
50 using namespace loc_core;
51
GnssAdapter()52 GnssAdapter::GnssAdapter() :
53 LocAdapterBase(0,
54 LocDualContext::getLocFgContext(NULL,
55 NULL,
56 LocDualContext::mLocationHalName,
57 false)),
58 mUlpProxy(new UlpProxyBase()),
59 mUlpPositionMode(),
60 mGnssSvIdUsedInPosition(),
61 mGnssSvIdUsedInPosAvail(false),
62 mControlCallbacks(),
63 mPowerVoteId(0),
64 mNiData(),
65 mAgpsManager()
66 {
67 LOC_LOGD("%s]: Constructor %p", __func__, this);
68 mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID;
69 readConfigCommand();
70 setConfigCommand();
71
72 }
73
74 inline
~GnssAdapter()75 GnssAdapter::~GnssAdapter()
76 {
77 LOC_LOGD("%s]: Destructor", __func__);
78 delete mUlpProxy;
79 }
80
81 void
setControlCallbacksCommand(LocationControlCallbacks & controlCallbacks)82 GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
83 {
84 struct MsgSetControlCallbacks : public LocMsg {
85 GnssAdapter& mAdapter;
86 const LocationControlCallbacks mControlCallbacks;
87 inline MsgSetControlCallbacks(GnssAdapter& adapter,
88 LocationControlCallbacks& controlCallbacks) :
89 LocMsg(),
90 mAdapter(adapter),
91 mControlCallbacks(controlCallbacks) {}
92 inline virtual void proc() const {
93 mAdapter.setControlCallbacks(mControlCallbacks);
94 }
95 };
96
97 sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
98 }
99
100 void
convertOptions(LocPosMode & out,const LocationOptions & options)101 GnssAdapter::convertOptions(LocPosMode& out, const LocationOptions& options)
102 {
103 LocPosMode locPosMode = {};
104 switch (options.mode) {
105 case GNSS_SUPL_MODE_MSB:
106 out.mode = LOC_POSITION_MODE_MS_BASED;
107 break;
108 case GNSS_SUPL_MODE_MSA:
109 out.mode = LOC_POSITION_MODE_MS_ASSISTED;
110 break;
111 default:
112 out.mode = LOC_POSITION_MODE_STANDALONE;
113 break;
114 }
115 out.share_position = true;
116 out.min_interval = options.minInterval;
117 }
118
119 void
convertLocation(Location & out,const LocGpsLocation & locGpsLocation,const GpsLocationExtended & locationExtended,const LocPosTechMask techMask)120 GnssAdapter::convertLocation(Location& out, const LocGpsLocation& locGpsLocation,
121 const GpsLocationExtended& locationExtended,
122 const LocPosTechMask techMask)
123 {
124 out.size = sizeof(Location);
125 if (LOC_GPS_LOCATION_HAS_LAT_LONG & locGpsLocation.flags) {
126 out.flags |= LOCATION_HAS_LAT_LONG_BIT;
127 out.latitude = locGpsLocation.latitude;
128 out.longitude = locGpsLocation.longitude;
129 }
130 if (LOC_GPS_LOCATION_HAS_ALTITUDE & locGpsLocation.flags) {
131 out.flags |= LOCATION_HAS_ALTITUDE_BIT;
132 out.altitude = locGpsLocation.altitude;
133 }
134 if (LOC_GPS_LOCATION_HAS_SPEED & locGpsLocation.flags) {
135 out.flags |= LOCATION_HAS_SPEED_BIT;
136 out.speed = locGpsLocation.speed;
137 }
138 if (LOC_GPS_LOCATION_HAS_BEARING & locGpsLocation.flags) {
139 out.flags |= LOCATION_HAS_BEARING_BIT;
140 out.bearing = locGpsLocation.bearing;
141 }
142 if (LOC_GPS_LOCATION_HAS_ACCURACY & locGpsLocation.flags) {
143 out.flags |= LOCATION_HAS_ACCURACY_BIT;
144 out.accuracy = locGpsLocation.accuracy;
145 }
146 if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
147 out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
148 out.verticalAccuracy = locationExtended.vert_unc;
149 }
150 if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
151 out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
152 out.speedAccuracy = locationExtended.speed_unc;
153 }
154 if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
155 out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
156 out.bearingAccuracy = locationExtended.bearing_unc;
157 }
158 out.timestamp = locGpsLocation.timestamp;
159 if (LOC_POS_TECH_MASK_SATELLITE & techMask) {
160 out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
161 }
162 if (LOC_POS_TECH_MASK_CELLID & techMask) {
163 out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
164 }
165 if (LOC_POS_TECH_MASK_WIFI & techMask) {
166 out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
167 }
168 if (LOC_POS_TECH_MASK_SENSORS & techMask) {
169 out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
170 }
171 }
172
173 void
convertLocationInfo(GnssLocationInfoNotification & out,const GpsLocationExtended & locationExtended)174 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
175 const GpsLocationExtended& locationExtended)
176 {
177 out.size = sizeof(GnssLocationInfoNotification);
178 if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
179 out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
180 out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
181 }
182 if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
183 out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
184 out.pdop = locationExtended.pdop;
185 out.hdop = locationExtended.hdop;
186 out.vdop = locationExtended.vdop;
187 }
188 if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
189 out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
190 out.magneticDeviation = locationExtended.magneticDeviation;
191 }
192 if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
193 out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
194 switch (locationExtended.horizontal_reliability) {
195 case LOC_RELIABILITY_VERY_LOW:
196 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
197 break;
198 case LOC_RELIABILITY_LOW:
199 out.horReliability = LOCATION_RELIABILITY_LOW;
200 break;
201 case LOC_RELIABILITY_MEDIUM:
202 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
203 break;
204 case LOC_RELIABILITY_HIGH:
205 out.horReliability = LOCATION_RELIABILITY_HIGH;
206 break;
207 default:
208 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
209 break;
210 }
211 }
212 if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
213 out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
214 switch (locationExtended.vertical_reliability) {
215 case LOC_RELIABILITY_VERY_LOW:
216 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
217 break;
218 case LOC_RELIABILITY_LOW:
219 out.verReliability = LOCATION_RELIABILITY_LOW;
220 break;
221 case LOC_RELIABILITY_MEDIUM:
222 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
223 break;
224 case LOC_RELIABILITY_HIGH:
225 out.verReliability = LOCATION_RELIABILITY_HIGH;
226 break;
227 default:
228 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
229 break;
230 }
231 }
232 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
233 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
234 out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
235 }
236 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
237 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
238 out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
239 }
240 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
241 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
242 out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
243 }
244 }
245
246 inline uint32_t
convertGpsLock(const GnssConfigGpsLock gpsLock)247 GnssAdapter::convertGpsLock(const GnssConfigGpsLock gpsLock)
248 {
249 switch (gpsLock) {
250 case GNSS_CONFIG_GPS_LOCK_MO:
251 return 1;
252 case GNSS_CONFIG_GPS_LOCK_NI:
253 return 2;
254 case GNSS_CONFIG_GPS_LOCK_MO_AND_NI:
255 return 3;
256 case GNSS_CONFIG_GPS_LOCK_NONE:
257 default:
258 return 0;
259 }
260 }
261
262 inline GnssConfigGpsLock
convertGpsLock(const uint32_t gpsLock)263 GnssAdapter::convertGpsLock(const uint32_t gpsLock)
264 {
265 switch (gpsLock) {
266 case 1:
267 return GNSS_CONFIG_GPS_LOCK_MO;
268 case 2:
269 return GNSS_CONFIG_GPS_LOCK_NI;
270 case 3:
271 return GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
272 case 0:
273 default:
274 return GNSS_CONFIG_GPS_LOCK_NONE;
275 }
276 }
277
278 inline uint32_t
convertSuplVersion(const GnssConfigSuplVersion suplVersion)279 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
280 {
281 switch (suplVersion) {
282 case GNSS_CONFIG_SUPL_VERSION_2_0_0:
283 return 0x00020000;
284 case GNSS_CONFIG_SUPL_VERSION_2_0_2:
285 return 0x00020002;
286 case GNSS_CONFIG_SUPL_VERSION_1_0_0:
287 default:
288 return 0x00010000;
289 }
290 }
291
292 inline GnssConfigSuplVersion
convertSuplVersion(const uint32_t suplVersion)293 GnssAdapter::convertSuplVersion(const uint32_t suplVersion)
294 {
295 switch (suplVersion) {
296 case 0x00020000:
297 return GNSS_CONFIG_SUPL_VERSION_2_0_0;
298 case 0x00020002:
299 return GNSS_CONFIG_SUPL_VERSION_2_0_2;
300 case 0x00010000:
301 default:
302 return GNSS_CONFIG_SUPL_VERSION_1_0_0;
303 }
304 }
305
306 inline uint32_t
convertLppProfile(const GnssConfigLppProfile lppProfile)307 GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile)
308 {
309 switch (lppProfile) {
310 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE:
311 return 1;
312 case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE:
313 return 2;
314 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE:
315 return 3;
316 case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE:
317 default:
318 return 0;
319 }
320 }
321
322 inline GnssConfigLppProfile
convertLppProfile(const uint32_t lppProfile)323 GnssAdapter::convertLppProfile(const uint32_t lppProfile)
324 {
325 switch (lppProfile) {
326 case 1:
327 return GNSS_CONFIG_LPP_PROFILE_USER_PLANE;
328 case 2:
329 return GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE;
330 case 3:
331 return GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE;
332 case 0:
333 default:
334 return GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE;
335 }
336 }
337
338 uint32_t
convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)339 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
340 {
341 uint32_t mask = 0;
342 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
343 mask |= (1<<0);
344 }
345 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
346 mask |= (1<<1);
347 }
348 return mask;
349 }
350
351 GnssConfigLppeControlPlaneMask
convertLppeCp(const uint32_t lppeControlPlaneMask)352 GnssAdapter::convertLppeCp(const uint32_t lppeControlPlaneMask)
353 {
354 GnssConfigLppeControlPlaneMask mask = 0;
355 if ((1<<0) & lppeControlPlaneMask) {
356 mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT;
357 }
358 if ((1<<1) & lppeControlPlaneMask) {
359 mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT;
360 }
361 return mask;
362 }
363
364
365 uint32_t
convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)366 GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
367 {
368 uint32_t mask = 0;
369 if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
370 mask |= (1<<0);
371 }
372 if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
373 mask |= (1<<1);
374 }
375 return mask;
376 }
377
378 GnssConfigLppeUserPlaneMask
convertLppeUp(const uint32_t lppeUserPlaneMask)379 GnssAdapter::convertLppeUp(const uint32_t lppeUserPlaneMask)
380 {
381 GnssConfigLppeUserPlaneMask mask = 0;
382 if ((1<<0) & lppeUserPlaneMask) {
383 mask |= GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT;
384 }
385 if ((1<<1) & lppeUserPlaneMask) {
386 mask |= GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT;
387 }
388 return mask;
389 }
390
391 uint32_t
convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)392 GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
393 {
394 uint32_t mask = 0;
395 if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
396 mask |= (1<<0);
397 }
398 if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
399 mask |= (1<<1);
400 }
401 if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
402 mask |= (1<<2);
403 }
404 if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
405 mask |= (1<<3);
406 }
407 return mask;
408 }
409
410 uint32_t
convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)411 GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
412 {
413 switch (emergencyPdnForEmergencySupl) {
414 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
415 return 1;
416 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
417 default:
418 return 0;
419 }
420 }
421
422 uint32_t
convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)423 GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
424 {
425 switch (suplEmergencyServices) {
426 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
427 return 1;
428 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
429 default:
430 return 0;
431 }
432 }
433
434 uint32_t
convertSuplMode(const GnssConfigSuplModeMask suplModeMask)435 GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
436 {
437 uint32_t mask = 0;
438 if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
439 mask |= (1<<0);
440 }
441 if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
442 mask |= (1<<1);
443 }
444 return mask;
445 }
446
447 bool
resolveInAddress(const char * hostAddress,struct in_addr * inAddress)448 GnssAdapter::resolveInAddress(const char* hostAddress, struct in_addr* inAddress)
449 {
450 bool ret = true;
451
452 struct hostent* hp;
453 hp = gethostbyname(hostAddress);
454 if (hp != NULL) { /* DNS OK */
455 memcpy(inAddress, hp->h_addr_list[0], hp->h_length);
456 } else {
457 /* Try IP representation */
458 if (inet_aton(hostAddress, inAddress) == 0) {
459 /* IP not valid */
460 LOC_LOGE("%s]: DNS query on '%s' failed", __func__, hostAddress);
461 ret = false;
462 }
463 }
464
465 return ret;
466 }
467
468 void
readConfigCommand()469 GnssAdapter::readConfigCommand()
470 {
471 LOC_LOGD("%s]: ", __func__);
472
473 struct MsgReadConfig : public LocMsg {
474 GnssAdapter* mAdapter;
475 ContextBase& mContext;
476 inline MsgReadConfig(GnssAdapter* adapter,
477 ContextBase& context) :
478 LocMsg(),
479 mAdapter(adapter),
480 mContext(context) {}
481 inline virtual void proc() const {
482 // reads config into mContext->mGps_conf
483 mContext.readConfig();
484 mContext.requestUlp((LocAdapterBase*)mAdapter, mContext.getCarrierCapabilities());
485 }
486 };
487
488 if (mContext != NULL) {
489 sendMsg(new MsgReadConfig(this, *mContext));
490 }
491 }
492
493 void
setConfigCommand()494 GnssAdapter::setConfigCommand()
495 {
496 LOC_LOGD("%s]: ", __func__);
497
498 struct MsgSetConfig : public LocMsg {
499 GnssAdapter& mAdapter;
500 LocApiBase& mApi;
501 inline MsgSetConfig(GnssAdapter& adapter,
502 LocApiBase& api) :
503 LocMsg(),
504 mAdapter(adapter),
505 mApi(api) {}
506 inline virtual void proc() const {
507 LocDualContext::injectFeatureConfig(mAdapter.getContext());
508 mApi.setSUPLVersion(mAdapter.convertSuplVersion(ContextBase::mGps_conf.SUPL_VER));
509 mApi.setLPPConfig(mAdapter.convertLppProfile(ContextBase::mGps_conf.LPP_PROFILE));
510 mApi.setSensorControlConfig(ContextBase::mSap_conf.SENSOR_USAGE,
511 ContextBase::mSap_conf.SENSOR_PROVIDER);
512 mApi.setAGLONASSProtocol(ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT);
513 mApi.setLPPeProtocolCp(
514 mAdapter.convertLppeCp(ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY));
515 mApi.setLPPeProtocolUp(
516 mAdapter.convertLppeUp(ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY));
517
518 // set nmea mask type
519 uint32_t mask = 0;
520 if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
521 mask = LOC_NMEA_ALL_SUPPORTED_MASK;
522 } else {
523 mask = LOC_NMEA_MASK_DEBUG_V02;
524 }
525 mApi.setNMEATypes(mask);
526
527 mApi.setXtraVersionCheck(ContextBase::mGps_conf.XTRA_VERSION_CHECK);
528 if (ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID ||
529 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
530 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
531 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
532 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
533 mApi.setSensorProperties(
534 ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID,
535 ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK,
536 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
537 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
538 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
539 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
540 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
541 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
542 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
543 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
544 }
545 mApi.setSensorPerfControlConfig(
546 ContextBase::mSap_conf.SENSOR_CONTROL_MODE,
547 ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
548 ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC,
549 ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH,
550 ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC,
551 ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
552 ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
553 ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
554 ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
555 ContextBase::mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK);
556 }
557 };
558
559 sendMsg(new MsgSetConfig(*this, *mLocApi));
560 }
561
562 uint32_t*
gnssUpdateConfigCommand(GnssConfig config)563 GnssAdapter::gnssUpdateConfigCommand(GnssConfig config)
564 {
565 // count the number of bits set
566 GnssConfigFlagsMask flagsCopy = config.flags;
567 size_t count = 0;
568 while (flagsCopy > 0) {
569 if (flagsCopy & 1) {
570 count++;
571 }
572 flagsCopy >>= 1;
573 }
574 std::string idsString = "[";
575 uint32_t* ids = NULL;
576 if (count > 0) {
577 ids = new uint32_t[count];
578 for (size_t i=0; i < count; ++i) {
579 ids[i] = generateSessionId();
580 IF_LOC_LOGD {
581 idsString += std::to_string(ids[i]) + " ";
582 }
583 }
584 }
585 idsString += "]";
586
587 LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
588
589 struct MsgGnssUpdateConfig : public LocMsg {
590 GnssAdapter& mAdapter;
591 LocApiBase& mApi;
592 GnssConfig mConfig;
593 uint32_t* mIds;
594 size_t mCount;
595 inline MsgGnssUpdateConfig(GnssAdapter& adapter,
596 LocApiBase& api,
597 GnssConfig config,
598 uint32_t* ids,
599 size_t count) :
600 LocMsg(),
601 mAdapter(adapter),
602 mApi(api),
603 mConfig(config),
604 mIds(ids),
605 mCount(count) {}
606 inline virtual ~MsgGnssUpdateConfig()
607 {
608 delete[] mIds;
609 }
610 inline virtual void proc() const {
611 //const size_t MAX_BITS_COUNT = 10;
612 //LocationError errs[MAX_BITS_COUNT] = {};
613 LocationError* errs = new LocationError[mCount];
614 LocationError err = LOCATION_ERROR_SUCCESS;
615 uint32_t index = 0;
616
617 if (mConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
618 uint32_t newGpsLock = mAdapter.convertGpsLock(mConfig.gpsLock);
619 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
620 if (0 == mAdapter.getPowerVoteId()) {
621 err = mApi.setGpsLock(mConfig.gpsLock);
622 }
623 if (index < mCount) {
624 errs[index++] = err;
625 }
626 }
627 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
628 uint32_t newSuplVersion = mAdapter.convertSuplVersion(mConfig.suplVersion);
629 if (newSuplVersion != ContextBase::mGps_conf.SUPL_VER) {
630 ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
631 err = mApi.setSUPLVersion(mConfig.suplVersion);
632 } else {
633 err = LOCATION_ERROR_SUCCESS;
634 }
635 if (index < mCount) {
636 errs[index++] = err;
637 }
638 }
639 if (mConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
640 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
641 char serverUrl[MAX_URL_LEN] = {};
642 uint32_t length = 0;
643 const char noHost[] = "NONE";
644 if (NULL == mConfig.assistanceServer.hostName ||
645 strncasecmp(noHost,
646 mConfig.assistanceServer.hostName,
647 sizeof(noHost)) == 0) {
648 } else {
649 length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u",
650 mConfig.assistanceServer.hostName,
651 mConfig.assistanceServer.port);
652 }
653
654 if (sizeof(serverUrl) > length) {
655 err = mApi.setServer(serverUrl, length);
656 } else {
657 err = LOCATION_ERROR_INVALID_PARAMETER;
658 }
659 } else if (GNSS_ASSISTANCE_TYPE_C2K == mConfig.assistanceServer.type) {
660 struct in_addr addr;
661 if (!mAdapter.resolveInAddress(mConfig.assistanceServer.hostName, &addr)) {
662 LOC_LOGE("%s]: hostName %s cannot be resolved",
663 __func__, mConfig.assistanceServer.hostName);
664 err = LOCATION_ERROR_INVALID_PARAMETER;
665 } else {
666 unsigned int ip = htonl(addr.s_addr);
667 err = mApi.setServer(ip, mConfig.assistanceServer.port,
668 LOC_AGPS_CDMA_PDE_SERVER);
669 }
670 } else {
671 LOC_LOGE("%s]: Not a valid gnss assistance type %u",
672 __func__, mConfig.assistanceServer.type);
673 err = LOCATION_ERROR_INVALID_PARAMETER;
674 }
675 if (index < mCount) {
676 errs[index++] = err;
677 }
678 }
679 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
680 uint32_t newLppProfile = mAdapter.convertLppProfile(mConfig.lppProfile);
681 if (newLppProfile != ContextBase::mGps_conf.LPP_PROFILE) {
682 ContextBase::mGps_conf.LPP_PROFILE = newLppProfile;
683 err = mApi.setLPPConfig(mConfig.lppProfile);
684 } else {
685 err = LOCATION_ERROR_SUCCESS;
686 }
687 if (index < mCount) {
688 errs[index++] = err;
689 }
690 }
691 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
692 uint32_t newLppeControlPlaneMask =
693 mAdapter.convertLppeCp(mConfig.lppeControlPlaneMask);
694 if (newLppeControlPlaneMask != ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY) {
695 ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
696 err = mApi.setLPPeProtocolCp(mConfig.lppeControlPlaneMask);
697 } else {
698 err = LOCATION_ERROR_SUCCESS;
699 }
700 if (index < mCount) {
701 errs[index++] = err;
702 }
703 }
704 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
705 uint32_t newLppeUserPlaneMask =
706 mAdapter.convertLppeUp(mConfig.lppeUserPlaneMask);
707 if (newLppeUserPlaneMask != ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY) {
708 ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
709 err = mApi.setLPPeProtocolUp(mConfig.lppeUserPlaneMask);
710 } else {
711 err = LOCATION_ERROR_SUCCESS;
712 }
713 if (index < mCount) {
714 errs[index++] = err;
715 }
716 }
717 if (mConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
718 uint32_t newAGloProtMask =
719 mAdapter.convertAGloProt(mConfig.aGlonassPositionProtocolMask);
720 if (newAGloProtMask != ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT) {
721 ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
722 err = mApi.setAGLONASSProtocol(mConfig.aGlonassPositionProtocolMask);
723 } else {
724 err = LOCATION_ERROR_SUCCESS;
725 }
726 if (index < mCount) {
727 errs[index++] = err;
728 }
729 }
730 if (mConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
731 uint32_t newEP4ES = mAdapter.convertEP4ES(mConfig.emergencyPdnForEmergencySupl);
732 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
733 ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
734 }
735 err = LOCATION_ERROR_SUCCESS;
736 if (index < mCount) {
737 errs[index++] = err;
738 }
739 }
740 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
741 uint32_t newSuplEs = mAdapter.convertSuplEs(mConfig.suplEmergencyServices);
742 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
743 ContextBase::mGps_conf.SUPL_ES = newSuplEs;
744 }
745 err = LOCATION_ERROR_SUCCESS;
746 if (index < mCount) {
747 errs[index++] = err;
748 }
749 }
750 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
751 uint32_t newSuplMode = mAdapter.convertSuplMode(mConfig.suplModeMask);
752 if (newSuplMode != ContextBase::mGps_conf.SUPL_MODE) {
753 ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
754 mAdapter.getUlpProxy()->setCapabilities(
755 ContextBase::getCarrierCapabilities());
756 }
757 err = LOCATION_ERROR_SUCCESS;
758 if (index < mCount) {
759 errs[index++] = err;
760 }
761 }
762
763 mAdapter.reportResponse(index, errs, mIds);
764 delete[] errs;
765 }
766 };
767
768 if (NULL != ids) {
769 sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
770 } else {
771 LOC_LOGE("%s]: No GNSS config items to update", __func__);
772 }
773
774 return ids;
775 }
776
777 uint32_t
gnssDeleteAidingDataCommand(GnssAidingData & data)778 GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
779 {
780 uint32_t sessionId = generateSessionId();
781 LOC_LOGD("%s]: id %u", __func__, sessionId);
782
783 struct MsgDeleteAidingData : public LocMsg {
784 GnssAdapter& mAdapter;
785 LocApiBase& mApi;
786 uint32_t mSessionId;
787 GnssAidingData mData;
788 inline MsgDeleteAidingData(GnssAdapter& adapter,
789 LocApiBase& api,
790 uint32_t sessionId,
791 GnssAidingData& data) :
792 LocMsg(),
793 mAdapter(adapter),
794 mApi(api),
795 mSessionId(sessionId),
796 mData(data) {}
797 inline virtual void proc() const {
798 LocationError err = LOCATION_ERROR_SUCCESS;
799 err = mApi.deleteAidingData(mData);
800 mAdapter.reportResponse(err, mSessionId);
801 }
802 };
803
804 sendMsg(new MsgDeleteAidingData(*this, *mLocApi, sessionId, data));
805 return sessionId;
806 }
807
808 void
injectLocationCommand(double latitude,double longitude,float accuracy)809 GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
810 {
811 LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
812 __func__, latitude, longitude, accuracy);
813
814 struct MsgInjectLocation : public LocMsg {
815 LocApiBase& mApi;
816 ContextBase& mContext;
817 double mLatitude;
818 double mLongitude;
819 float mAccuracy;
820 inline MsgInjectLocation(LocApiBase& api,
821 ContextBase& context,
822 double latitude,
823 double longitude,
824 float accuracy) :
825 LocMsg(),
826 mApi(api),
827 mContext(context),
828 mLatitude(latitude),
829 mLongitude(longitude),
830 mAccuracy(accuracy) {}
831 inline virtual void proc() const {
832 if (!mContext.hasCPIExtendedCapabilities()) {
833 mApi.injectPosition(mLatitude, mLongitude, mAccuracy);
834 }
835 }
836 };
837
838 sendMsg(new MsgInjectLocation(*mLocApi, *mContext, latitude, longitude, accuracy));
839 }
840
841 void
injectTimeCommand(int64_t time,int64_t timeReference,int32_t uncertainty)842 GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
843 {
844 LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
845 __func__, (long long)time, (long long)timeReference, uncertainty);
846
847 struct MsgInjectTime : public LocMsg {
848 LocApiBase& mApi;
849 ContextBase& mContext;
850 int64_t mTime;
851 int64_t mTimeReference;
852 int32_t mUncertainty;
853 inline MsgInjectTime(LocApiBase& api,
854 ContextBase& context,
855 int64_t time,
856 int64_t timeReference,
857 int32_t uncertainty) :
858 LocMsg(),
859 mApi(api),
860 mContext(context),
861 mTime(time),
862 mTimeReference(timeReference),
863 mUncertainty(uncertainty) {}
864 inline virtual void proc() const {
865 mApi.setTime(mTime, mTimeReference, mUncertainty);
866 }
867 };
868
869 sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
870 }
871
872 void
setUlpProxyCommand(UlpProxyBase * ulp)873 GnssAdapter::setUlpProxyCommand(UlpProxyBase* ulp)
874 {
875 LOC_LOGD("%s]: ", __func__);
876
877 struct MsgSetUlpProxy : public LocMsg {
878 GnssAdapter& mAdapter;
879 UlpProxyBase* mUlp;
880 inline MsgSetUlpProxy(GnssAdapter& adapter,
881 UlpProxyBase* ulp) :
882 LocMsg(),
883 mAdapter(adapter),
884 mUlp(ulp) {}
885 inline virtual void proc() const {
886 mAdapter.setUlpProxy(mUlp);
887 }
888 };
889
890 sendMsg(new MsgSetUlpProxy(*this, ulp));
891 }
892
893 void
setUlpProxy(UlpProxyBase * ulp)894 GnssAdapter::setUlpProxy(UlpProxyBase* ulp)
895 {
896 if (ulp == mUlpProxy) {
897 //This takes care of the case when double initalization happens
898 //and we get the same object back for UlpProxyBase . Do nothing
899 return;
900 }
901
902 LOC_LOGV("%s]: %p", __func__, ulp);
903 if (NULL == ulp) {
904 LOC_LOGE("%s]: ulp pointer is NULL", __func__);
905 ulp = new UlpProxyBase();
906 }
907
908 if (LOC_POSITION_MODE_INVALID != mUlpProxy->mPosMode.mode) {
909 // need to send this mode and start msg to ULP
910 ulp->sendFixMode(mUlpProxy->mPosMode);
911 }
912
913 if (mUlpProxy->mFixSet) {
914 ulp->sendStartFix();
915 }
916
917 delete mUlpProxy;
918 mUlpProxy = ulp;
919 }
920
921 void
addClientCommand(LocationAPI * client,const LocationCallbacks & callbacks)922 GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
923 {
924 LOC_LOGD("%s]: client %p", __func__, client);
925
926 struct MsgAddClient : public LocMsg {
927 GnssAdapter& mAdapter;
928 LocationAPI* mClient;
929 const LocationCallbacks mCallbacks;
930 inline MsgAddClient(GnssAdapter& adapter,
931 LocationAPI* client,
932 const LocationCallbacks& callbacks) :
933 LocMsg(),
934 mAdapter(adapter),
935 mClient(client),
936 mCallbacks(callbacks) {}
937 inline virtual void proc() const {
938 mAdapter.saveClient(mClient, mCallbacks);
939 }
940 };
941
942 sendMsg(new MsgAddClient(*this, client, callbacks));
943 }
944
945 void
removeClientCommand(LocationAPI * client)946 GnssAdapter::removeClientCommand(LocationAPI* client)
947 {
948 LOC_LOGD("%s]: client %p", __func__, client);
949
950 struct MsgRemoveClient : public LocMsg {
951 GnssAdapter& mAdapter;
952 LocationAPI* mClient;
953 inline MsgRemoveClient(GnssAdapter& adapter,
954 LocationAPI* client) :
955 LocMsg(),
956 mAdapter(adapter),
957 mClient(client) {}
958 inline virtual void proc() const {
959 mAdapter.stopClientSessions(mClient);
960 mAdapter.eraseClient(mClient);
961 }
962 };
963
964 sendMsg(new MsgRemoveClient(*this, client));
965 }
966
967 void
stopClientSessions(LocationAPI * client)968 GnssAdapter::stopClientSessions(LocationAPI* client)
969 {
970 LOC_LOGD("%s]: client %p", __func__, client);
971 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) {
972 if (client == it->first.client) {
973 LocationError err = stopTrackingMultiplex(it->first.client, it->first.id);
974 if (LOCATION_ERROR_SUCCESS == err) {
975 it = mTrackingSessions.erase(it);
976 continue;
977 }
978 }
979 ++it; // increment only when not erasing an iterator
980 }
981
982 }
983
984 void
updateClientsEventMask()985 GnssAdapter::updateClientsEventMask()
986 {
987 LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
988 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
989 if (it->second.trackingCb != nullptr) {
990 mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
991 }
992 if (it->second.gnssNiCb != nullptr) {
993 mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
994 }
995 if (it->second.gnssSvCb != nullptr) {
996 mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
997 }
998 if (it->second.gnssNmeaCb != nullptr) {
999 mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
1000 }
1001 if (it->second.gnssMeasurementsCb != nullptr) {
1002 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
1003 }
1004 }
1005 updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
1006 }
1007
1008 void
handleEngineUpEvent()1009 GnssAdapter::handleEngineUpEvent()
1010 {
1011 struct MsgRestartSessions : public LocMsg {
1012 GnssAdapter& mAdapter;
1013 inline MsgRestartSessions(GnssAdapter& adapter) :
1014 LocMsg(),
1015 mAdapter(adapter) {}
1016 virtual void proc() const {
1017 mAdapter.restartSessions();
1018 }
1019 };
1020
1021 setConfigCommand();
1022 sendMsg(new MsgRestartSessions(*this));
1023 }
1024
1025 void
restartSessions()1026 GnssAdapter::restartSessions()
1027 {
1028 LOC_LOGD("%s]: ", __func__);
1029
1030 if (mTrackingSessions.empty()) {
1031 return;
1032 }
1033
1034 // get the LocationOptions that has the smallest interval, which should be the active one
1035 LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
1036 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
1037 if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
1038 it->second.minInterval < smallestIntervalOptions.minInterval) {
1039 smallestIntervalOptions = it->second;
1040 }
1041 }
1042
1043 LocPosMode locPosMode = {};
1044 convertOptions(locPosMode, smallestIntervalOptions);
1045 mLocApi->startFix(locPosMode);
1046 }
1047
1048 void
requestCapabilitiesCommand(LocationAPI * client)1049 GnssAdapter::requestCapabilitiesCommand(LocationAPI* client)
1050 {
1051 LOC_LOGD("%s]: ", __func__);
1052
1053 struct MsgRequestCapabilities : public LocMsg {
1054 GnssAdapter& mAdapter;
1055 LocApiBase& mApi;
1056 LocationAPI* mClient;
1057 inline MsgRequestCapabilities(GnssAdapter& adapter,
1058 LocApiBase& api,
1059 LocationAPI* client) :
1060 LocMsg(),
1061 mAdapter(adapter),
1062 mApi(api),
1063 mClient(client) {}
1064 inline virtual void proc() const {
1065 LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient);
1066 if (callbacks.capabilitiesCb == nullptr) {
1067 LOC_LOGE("%s]: capabilitiesCb is NULL", __func__);
1068 return;
1069 }
1070
1071 LocationCapabilitiesMask mask = {};
1072 // time based tracking always supported
1073 mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT;
1074 if (mApi.isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)){
1075 mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT |
1076 LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT;
1077 }
1078 if (mApi.isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
1079 mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT;
1080 }
1081 // geofence always supported
1082 mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT;
1083 if (mApi.gnssConstellationConfig()) {
1084 mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT;
1085 }
1086 uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities();
1087 if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) {
1088 mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT;
1089 }
1090 if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) {
1091 mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT;
1092 }
1093
1094 callbacks.capabilitiesCb(mask);
1095 }
1096 };
1097
1098 sendMsg(new MsgRequestCapabilities(*this, *mLocApi, client));
1099 }
1100
1101 LocationCallbacks
getClientCallbacks(LocationAPI * client)1102 GnssAdapter::getClientCallbacks(LocationAPI* client)
1103 {
1104 LocationCallbacks callbacks = {};
1105 auto it = mClientData.find(client);
1106 if (it != mClientData.end()) {
1107 callbacks = it->second;
1108 }
1109 return callbacks;
1110 }
1111
1112 void
saveClient(LocationAPI * client,const LocationCallbacks & callbacks)1113 GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks)
1114 {
1115 mClientData[client] = callbacks;
1116 updateClientsEventMask();
1117 }
1118
1119 void
eraseClient(LocationAPI * client)1120 GnssAdapter::eraseClient(LocationAPI* client)
1121 {
1122 auto it = mClientData.find(client);
1123 if (it != mClientData.end()) {
1124 mClientData.erase(it);
1125 }
1126 updateClientsEventMask();
1127 }
1128
1129 bool
hasTrackingCallback(LocationAPI * client)1130 GnssAdapter::hasTrackingCallback(LocationAPI* client)
1131 {
1132 auto it = mClientData.find(client);
1133 return (it != mClientData.end() && it->second.trackingCb);
1134 }
1135
1136 bool
hasMeasurementsCallback(LocationAPI * client)1137 GnssAdapter::hasMeasurementsCallback(LocationAPI* client)
1138 {
1139 auto it = mClientData.find(client);
1140 return (it != mClientData.end() && it->second.gnssMeasurementsCb);
1141 }
1142
1143 bool
isTrackingSession(LocationAPI * client,uint32_t sessionId)1144 GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
1145 {
1146 LocationSessionKey key(client, sessionId);
1147 return (mTrackingSessions.find(key) != mTrackingSessions.end());
1148 }
1149
1150 void
saveTrackingSession(LocationAPI * client,uint32_t sessionId,const LocationOptions & options)1151 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
1152 const LocationOptions& options)
1153 {
1154 LocationSessionKey key(client, sessionId);
1155 mTrackingSessions[key] = options;
1156 }
1157
1158 void
eraseTrackingSession(LocationAPI * client,uint32_t sessionId)1159 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
1160 {
1161 LocationSessionKey key(client, sessionId);
1162 auto it = mTrackingSessions.find(key);
1163 if (it != mTrackingSessions.end()) {
1164 mTrackingSessions.erase(it);
1165 }
1166
1167 }
1168
1169 void
reportResponse(LocationAPI * client,LocationError err,uint32_t sessionId)1170 GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
1171 {
1172 LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
1173
1174 auto it = mClientData.find(client);
1175 if (it != mClientData.end() &&
1176 it->second.responseCb != nullptr) {
1177 it->second.responseCb(err, sessionId);
1178 } else {
1179 LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
1180 }
1181 }
1182
1183 void
reportResponse(LocationError err,uint32_t sessionId)1184 GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
1185 {
1186 LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
1187
1188 if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
1189 mControlCallbacks.responseCb(err, sessionId);
1190 } else {
1191 LOC_LOGW("%s]: control client response callback not found", __func__);
1192 }
1193 }
1194
1195 void
reportResponse(size_t count,LocationError * errs,uint32_t * ids)1196 GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
1197 {
1198 IF_LOC_LOGD {
1199 std::string idsString = "[";
1200 std::string errsString = "[";
1201 if (NULL != ids && NULL != errs) {
1202 for (size_t i=0; i < count; ++i) {
1203 idsString += std::to_string(ids[i]) + " ";
1204 errsString += std::to_string(errs[i]) + " ";
1205 }
1206 }
1207 idsString += "]";
1208 errsString += "]";
1209
1210 LOC_LOGD("%s]: ids %s errs %s",
1211 __func__, idsString.c_str(), errsString.c_str());
1212 }
1213
1214 if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
1215 mControlCallbacks.collectiveResponseCb(count, errs, ids);
1216 } else {
1217 LOC_LOGW("%s]: control client callback not found", __func__);
1218 }
1219 }
1220
1221 uint32_t
startTrackingCommand(LocationAPI * client,LocationOptions & options)1222 GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options)
1223 {
1224 uint32_t sessionId = generateSessionId();
1225 LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
1226 __func__, client, sessionId, options.minInterval, options.mode);
1227
1228 struct MsgStartTracking : public LocMsg {
1229 GnssAdapter& mAdapter;
1230 LocApiBase& mApi;
1231 LocationAPI* mClient;
1232 uint32_t mSessionId;
1233 LocationOptions mOptions;
1234 inline MsgStartTracking(GnssAdapter& adapter,
1235 LocApiBase& api,
1236 LocationAPI* client,
1237 uint32_t sessionId,
1238 LocationOptions options) :
1239 LocMsg(),
1240 mAdapter(adapter),
1241 mApi(api),
1242 mClient(client),
1243 mSessionId(sessionId),
1244 mOptions(options) {}
1245 inline virtual void proc() const {
1246 LocationError err = LOCATION_ERROR_SUCCESS;
1247 if (!mAdapter.hasTrackingCallback(mClient) &&
1248 !mAdapter.hasMeasurementsCallback(mClient)) {
1249 err = LOCATION_ERROR_CALLBACK_MISSING;
1250 } else if (0 == mOptions.size) {
1251 err = LOCATION_ERROR_INVALID_PARAMETER;
1252 } else {
1253 // Api doesn't support multiple clients for time based tracking, so mutiplex
1254 err = mAdapter.startTrackingMultiplex(mOptions);
1255 if (LOCATION_ERROR_SUCCESS == err) {
1256 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
1257 }
1258 }
1259 mAdapter.reportResponse(mClient, err, mSessionId);
1260 }
1261 };
1262
1263 sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
1264 return sessionId;
1265
1266 }
1267
1268 LocationError
startTrackingMultiplex(const LocationOptions & options)1269 GnssAdapter::startTrackingMultiplex(const LocationOptions& options)
1270 {
1271 LocationError err = LOCATION_ERROR_SUCCESS;
1272
1273 if (mTrackingSessions.empty()) {
1274 err = startTracking(options);
1275 } else {
1276 // get the LocationOptions that has the smallest interval, which should be the active one
1277 LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
1278 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
1279 if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
1280 it->second.minInterval < smallestIntervalOptions.minInterval) {
1281 smallestIntervalOptions = it->second;
1282 }
1283 }
1284 // if new session's minInterval is smaller than any in other sessions
1285 if (options.minInterval < smallestIntervalOptions.minInterval) {
1286 // restart time based tracking with new options
1287 err = startTracking(options);
1288 }
1289 }
1290
1291 return err;
1292 }
1293
1294 LocationError
startTracking(const LocationOptions & options)1295 GnssAdapter::startTracking(const LocationOptions& options)
1296 {
1297 LocationError err = LOCATION_ERROR_SUCCESS;
1298 LocPosMode locPosMode = {};
1299 convertOptions(locPosMode, options);
1300 if (!mUlpProxy->sendFixMode(locPosMode)) {
1301 // do nothing
1302 }
1303 if (!mUlpProxy->sendStartFix()) {
1304 loc_api_adapter_err apiErr = mLocApi->startFix(locPosMode);
1305 if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
1306 err = LOCATION_ERROR_SUCCESS;
1307 } else {
1308 err = LOCATION_ERROR_GENERAL_FAILURE;
1309 }
1310 }
1311
1312 return err;
1313 }
1314
1315 void
setPositionModeCommand(LocPosMode & locPosMode)1316 GnssAdapter::setPositionModeCommand(LocPosMode& locPosMode)
1317 {
1318 LOC_LOGD("%s]: min_interval %u mode %u",
1319 __func__, locPosMode.min_interval, locPosMode.mode);
1320
1321 struct MsgSetPositionMode : public LocMsg {
1322 GnssAdapter& mAdapter;
1323 LocApiBase& mApi;
1324 LocPosMode mLocPosMode;
1325 inline MsgSetPositionMode(GnssAdapter& adapter,
1326 LocApiBase& api,
1327 LocPosMode& locPosMode) :
1328 LocMsg(),
1329 mAdapter(adapter),
1330 mApi(api),
1331 mLocPosMode(locPosMode) {}
1332 inline virtual void proc() const {
1333 // saves the mode in adapter to be used when startTrackingCommand is called from ULP
1334 mAdapter.setUlpPositionMode(mLocPosMode);
1335 mApi.setPositionMode(mLocPosMode);
1336 }
1337 };
1338
1339 sendMsg(new MsgSetPositionMode(*this, *mLocApi, locPosMode));
1340 }
1341
1342 void
startTrackingCommand()1343 GnssAdapter::startTrackingCommand()
1344 {
1345 LOC_LOGD("%s]: ", __func__);
1346
1347 struct MsgStartTracking : public LocMsg {
1348 GnssAdapter& mAdapter;
1349 LocApiBase& mApi;
1350 inline MsgStartTracking(GnssAdapter& adapter,
1351 LocApiBase& api) :
1352 LocMsg(),
1353 mAdapter(adapter),
1354 mApi(api) {}
1355 inline virtual void proc() const {
1356 // we get this call from ULP, so just call LocApi without multiplexing because
1357 // ulp would be doing the multiplexing for us if it is present
1358 LocPosMode& ulpPositionMode = mAdapter.getUlpPositionMode();
1359 mApi.startFix(ulpPositionMode);
1360 }
1361 };
1362
1363 sendMsg(new MsgStartTracking(*this, *mLocApi));
1364 }
1365
1366 void
updateTrackingOptionsCommand(LocationAPI * client,uint32_t id,LocationOptions & options)1367 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
1368 LocationOptions& options)
1369 {
1370 LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
1371 __func__, client, id, options.minInterval, options.mode);
1372
1373 struct MsgUpdateTracking : public LocMsg {
1374 GnssAdapter& mAdapter;
1375 LocApiBase& mApi;
1376 LocationAPI* mClient;
1377 uint32_t mSessionId;
1378 LocationOptions mOptions;
1379 inline MsgUpdateTracking(GnssAdapter& adapter,
1380 LocApiBase& api,
1381 LocationAPI* client,
1382 uint32_t sessionId,
1383 LocationOptions options) :
1384 LocMsg(),
1385 mAdapter(adapter),
1386 mApi(api),
1387 mClient(client),
1388 mSessionId(sessionId),
1389 mOptions(options) {}
1390 inline virtual void proc() const {
1391 if (mAdapter.isTrackingSession(mClient, mSessionId)) {
1392 LocationError err = LOCATION_ERROR_SUCCESS;
1393 if (0 == mOptions.size) {
1394 err = LOCATION_ERROR_INVALID_PARAMETER;
1395 } else {
1396 // Api doesn't support multiple clients for time based tracking, so mutiplex
1397 err = mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions);
1398 if (LOCATION_ERROR_SUCCESS == err) {
1399 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
1400 }
1401 }
1402 mAdapter.reportResponse(mClient, err, mSessionId);
1403 }
1404 // we do not reportResponse for the case where there is no existing tracking session
1405 // for the client and id being used, since updateTrackingCommand can be sent to both
1406 // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
1407 }
1408 };
1409
1410 sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
1411 }
1412
1413 LocationError
updateTrackingMultiplex(LocationAPI * client,uint32_t id,const LocationOptions & options)1414 GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
1415 const LocationOptions& options)
1416 {
1417 LocationError err = LOCATION_ERROR_SUCCESS;
1418
1419 if (1 == mTrackingSessions.size()) {
1420 err = startTracking(options);
1421 } else {
1422 LocationSessionKey key(client, id);
1423
1424 // get the session we are updating
1425 auto it = mTrackingSessions.find(key);
1426 if (it != mTrackingSessions.end()) {
1427 // find the smallest interval, other than the session we are updating
1428 LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
1429 for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
1430 // if session is not the one we are updating and either smallest interval is not set
1431 // or there is a new smallest interval, then set the new smallest interval
1432 if (it2->first != key && (0 == smallestIntervalOptions.size ||
1433 it2->second.minInterval < smallestIntervalOptions.minInterval)) {
1434 smallestIntervalOptions = it2->second;
1435 }
1436 }
1437 // if session we are updating has smaller interval then next smallest
1438 if (options.minInterval < smallestIntervalOptions.minInterval) {
1439 // restart time based tracking with the newly updated interval
1440 err = startTracking(options);
1441 // else if the session we are updating used to be the smallest
1442 } else if (it->second.minInterval < smallestIntervalOptions.minInterval) {
1443 // restart time based tracking with the next smallest
1444 err = startTracking(smallestIntervalOptions);
1445 }
1446 }
1447 }
1448
1449 return err;
1450 }
1451
1452 void
stopTrackingCommand(LocationAPI * client,uint32_t id)1453 GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
1454 {
1455 LOC_LOGD("%s]: client %p id %u", __func__, client, id);
1456
1457 struct MsgStopTracking : public LocMsg {
1458 GnssAdapter& mAdapter;
1459 LocApiBase& mApi;
1460 LocationAPI* mClient;
1461 uint32_t mSessionId;
1462 inline MsgStopTracking(GnssAdapter& adapter,
1463 LocApiBase& api,
1464 LocationAPI* client,
1465 uint32_t sessionId) :
1466 LocMsg(),
1467 mAdapter(adapter),
1468 mApi(api),
1469 mClient(client),
1470 mSessionId(sessionId) {}
1471 inline virtual void proc() const {
1472 if (mAdapter.isTrackingSession(mClient, mSessionId)) {
1473 LocationError err = LOCATION_ERROR_SUCCESS;
1474 // Api doesn't support multiple clients for time based tracking, so mutiplex
1475 err = mAdapter.stopTrackingMultiplex(mClient, mSessionId);
1476 if (LOCATION_ERROR_SUCCESS == err) {
1477 mAdapter.eraseTrackingSession(mClient, mSessionId);
1478 }
1479 mAdapter.reportResponse(mClient, err, mSessionId);
1480 }
1481 // we do not reportResponse for the case where there is no existing tracking session
1482 // for the client and id being used, since stopTrackingCommand can be sent to both
1483 // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
1484
1485 }
1486 };
1487
1488 sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
1489 }
1490
1491 LocationError
stopTrackingMultiplex(LocationAPI * client,uint32_t id)1492 GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id)
1493 {
1494 LocationError err = LOCATION_ERROR_SUCCESS;
1495
1496 if (1 == mTrackingSessions.size()) {
1497 err = stopTracking();
1498 } else {
1499 LocationSessionKey key(client, id);
1500
1501 // get the session we are stopping
1502 auto it = mTrackingSessions.find(key);
1503 if (it != mTrackingSessions.end()) {
1504 // find the next smallest interval, other than the session we are stopping
1505 LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
1506 for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
1507 // if session is not the one we are stopping and either smallest interval is not set
1508 // or there is a new smallest interval, then set the new smallest interval
1509 if (it2->first != key && (0 == smallestIntervalOptions.size ||
1510 it2->second.minInterval < smallestIntervalOptions.minInterval)) {
1511 smallestIntervalOptions = it2->second;
1512 }
1513 }
1514 // if session we are stopping has smaller interval then next smallest
1515 if (it->second.minInterval < smallestIntervalOptions.minInterval) {
1516 // restart time based tracking with next smallest interval
1517 err = startTracking(smallestIntervalOptions);
1518 }
1519 }
1520 }
1521
1522 return err;
1523 }
1524
1525 LocationError
stopTracking()1526 GnssAdapter::stopTracking()
1527 {
1528 LocationError err = LOCATION_ERROR_SUCCESS;
1529 if (!mUlpProxy->sendStopFix()) {
1530 loc_api_adapter_err apiErr = mLocApi->stopFix();
1531 if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
1532 err = LOCATION_ERROR_SUCCESS;
1533 } else {
1534 err = LOCATION_ERROR_GENERAL_FAILURE;
1535 }
1536 }
1537
1538 return err;
1539 }
1540
1541 void
stopTrackingCommand()1542 GnssAdapter::stopTrackingCommand()
1543 {
1544 LOC_LOGD("%s]: ", __func__);
1545
1546 struct MsgStopTracking : public LocMsg {
1547 GnssAdapter& mAdapter;
1548 LocApiBase& mApi;
1549 inline MsgStopTracking(GnssAdapter& adapter,
1550 LocApiBase& api) :
1551 LocMsg(),
1552 mAdapter(adapter),
1553 mApi(api) {}
1554 inline virtual void proc() const {
1555 // clear the position mode
1556 LocPosMode mLocPosMode = {};
1557 mLocPosMode.mode = LOC_POSITION_MODE_INVALID;
1558 mAdapter.setUlpPositionMode(mLocPosMode);
1559 // don't need to multiplex because ULP will do that for us if it is present
1560 mApi.stopFix();
1561 }
1562 };
1563
1564 sendMsg(new MsgStopTracking(*this, *mLocApi));
1565 }
1566
1567 void
getZppCommand()1568 GnssAdapter::getZppCommand()
1569 {
1570 LOC_LOGD("%s]: ", __func__);
1571
1572 struct MsgGetZpp : public LocMsg {
1573 GnssAdapter& mAdapter;
1574 LocApiBase& mApi;
1575 inline MsgGetZpp(GnssAdapter& adapter,
1576 LocApiBase& api) :
1577 LocMsg(),
1578 mAdapter(adapter),
1579 mApi(api) {}
1580 inline virtual void proc() const {
1581 UlpLocation location = {};
1582 LocPosTechMask techMask = LOC_POS_TECH_MASK_DEFAULT;
1583 GpsLocationExtended locationExtended = {};
1584 locationExtended.size = sizeof(locationExtended);
1585
1586 mApi.getBestAvailableZppFix(location.gpsLocation, techMask);
1587 //Mark the location source as from ZPP
1588 location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO;
1589 location.position_source = ULP_LOCATION_IS_FROM_ZPP;
1590
1591 mAdapter.getUlpProxy()->reportPosition(location,
1592 locationExtended,
1593 LOC_SESS_SUCCESS,
1594 techMask);
1595 }
1596 };
1597
1598 sendMsg(new MsgGetZpp(*this, *mLocApi));
1599 }
1600
1601 bool
hasNiNotifyCallback(LocationAPI * client)1602 GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
1603 {
1604 auto it = mClientData.find(client);
1605 return (it != mClientData.end() && it->second.gnssNiCb);
1606 }
1607
1608 void
gnssNiResponseCommand(LocationAPI * client,uint32_t id,GnssNiResponse response)1609 GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
1610 uint32_t id,
1611 GnssNiResponse response)
1612 {
1613 LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
1614
1615 struct MsgGnssNiResponse : public LocMsg {
1616 GnssAdapter& mAdapter;
1617 LocationAPI* mClient;
1618 uint32_t mSessionId;
1619 GnssNiResponse mResponse;
1620 inline MsgGnssNiResponse(GnssAdapter& adapter,
1621 LocationAPI* client,
1622 uint32_t sessionId,
1623 GnssNiResponse response) :
1624 LocMsg(),
1625 mAdapter(adapter),
1626 mClient(client),
1627 mSessionId(sessionId),
1628 mResponse(response) {}
1629 inline virtual void proc() const {
1630 NiData& niData = mAdapter.getNiData();
1631 LocationError err = LOCATION_ERROR_SUCCESS;
1632 if (!mAdapter.hasNiNotifyCallback(mClient)) {
1633 err = LOCATION_ERROR_ID_UNKNOWN;
1634 } else {
1635 NiSession* pSession = NULL;
1636 if (mSessionId == niData.sessionEs.reqID &&
1637 NULL != niData.sessionEs.rawRequest) {
1638 pSession = &niData.sessionEs;
1639 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
1640 if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
1641 NULL != niData.session.rawRequest) {
1642 pthread_mutex_lock(&niData.session.tLock);
1643 niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
1644 niData.session.respRecvd = true;
1645 pthread_cond_signal(&niData.session.tCond);
1646 pthread_mutex_unlock(&niData.session.tLock);
1647 }
1648 } else if (mSessionId == niData.session.reqID &&
1649 NULL != niData.session.rawRequest) {
1650 pSession = &niData.session;
1651 }
1652
1653 if (pSession) {
1654 LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
1655 __func__, mResponse, mSessionId);
1656 pthread_mutex_lock(&pSession->tLock);
1657 pSession->resp = mResponse;
1658 pSession->respRecvd = true;
1659 pthread_cond_signal(&pSession->tCond);
1660 pthread_mutex_unlock(&pSession->tLock);
1661 } else {
1662 err = LOCATION_ERROR_ID_UNKNOWN;
1663 LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
1664 __func__, mSessionId);
1665 }
1666 }
1667 mAdapter.reportResponse(mClient, err, mSessionId);
1668 }
1669 };
1670
1671 sendMsg(new MsgGnssNiResponse(*this, client, id, response));
1672
1673 }
1674
1675 void
gnssNiResponseCommand(GnssNiResponse response,void * rawRequest)1676 GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
1677 {
1678 LOC_LOGD("%s]: response %u", __func__, response);
1679
1680 struct MsgGnssNiResponse : public LocMsg {
1681 LocApiBase& mApi;
1682 const GnssNiResponse mResponse;
1683 const void* mPayload;
1684 inline MsgGnssNiResponse(LocApiBase& api,
1685 const GnssNiResponse response,
1686 const void* rawRequest) :
1687 LocMsg(),
1688 mApi(api),
1689 mResponse(response),
1690 mPayload(rawRequest) {}
1691 inline virtual ~MsgGnssNiResponse() {
1692 // this is a bit weird since mPayload is not
1693 // allocated by this class. But there is no better way.
1694 // mPayload actually won't be NULL here.
1695 free((void*)mPayload);
1696 }
1697 inline virtual void proc() const {
1698 mApi.informNiResponse(mResponse, mPayload);
1699 }
1700 };
1701
1702 sendMsg(new MsgGnssNiResponse(*mLocApi, response, rawRequest));
1703
1704 }
1705
1706 uint32_t
enableCommand(LocationTechnologyType techType)1707 GnssAdapter::enableCommand(LocationTechnologyType techType)
1708 {
1709 uint32_t sessionId = generateSessionId();
1710 LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
1711
1712 struct MsgEnableGnss : public LocMsg {
1713 GnssAdapter& mAdapter;
1714 LocApiBase& mApi;
1715 ContextBase& mContext;
1716 uint32_t mSessionId;
1717 LocationTechnologyType mTechType;
1718 inline MsgEnableGnss(GnssAdapter& adapter,
1719 LocApiBase& api,
1720 ContextBase& context,
1721 uint32_t sessionId,
1722 LocationTechnologyType techType) :
1723 LocMsg(),
1724 mAdapter(adapter),
1725 mApi(api),
1726 mContext(context),
1727 mSessionId(sessionId),
1728 mTechType(techType) {}
1729 inline virtual void proc() const {
1730 LocationError err = LOCATION_ERROR_SUCCESS;
1731 uint32_t powerVoteId = mAdapter.getPowerVoteId();
1732 if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
1733 err = LOCATION_ERROR_INVALID_PARAMETER;
1734 } else if (powerVoteId > 0) {
1735 err = LOCATION_ERROR_ALREADY_STARTED;
1736 } else {
1737 mContext.modemPowerVote(true);
1738 mAdapter.setPowerVoteId(mSessionId);
1739 mApi.setGpsLock(GNSS_CONFIG_GPS_LOCK_NONE);
1740 }
1741 mAdapter.reportResponse(err, mSessionId);
1742 }
1743 };
1744
1745 if (mContext != NULL) {
1746 sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
1747 } else {
1748 LOC_LOGE("%s]: Context is NULL", __func__);
1749 }
1750
1751 return sessionId;
1752 }
1753
1754 void
disableCommand(uint32_t id)1755 GnssAdapter::disableCommand(uint32_t id)
1756 {
1757 LOC_LOGD("%s]: id %u", __func__, id);
1758
1759 struct MsgDisableGnss : public LocMsg {
1760 GnssAdapter& mAdapter;
1761 LocApiBase& mApi;
1762 ContextBase& mContext;
1763 uint32_t mSessionId;
1764 inline MsgDisableGnss(GnssAdapter& adapter,
1765 LocApiBase& api,
1766 ContextBase& context,
1767 uint32_t sessionId) :
1768 LocMsg(),
1769 mAdapter(adapter),
1770 mApi(api),
1771 mContext(context),
1772 mSessionId(sessionId) {}
1773 inline virtual void proc() const {
1774 LocationError err = LOCATION_ERROR_SUCCESS;
1775 uint32_t powerVoteId = mAdapter.getPowerVoteId();
1776 if (powerVoteId != mSessionId) {
1777 err = LOCATION_ERROR_ID_UNKNOWN;
1778 } else {
1779 mContext.modemPowerVote(false);
1780 mAdapter.setPowerVoteId(0);
1781 mApi.setGpsLock(mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK));
1782 }
1783 mAdapter.reportResponse(err, mSessionId);
1784 }
1785 };
1786
1787 if (mContext != NULL) {
1788 sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
1789 }
1790
1791 }
1792
1793 void
reportPositionEvent(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask,bool fromUlp)1794 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
1795 const GpsLocationExtended& locationExtended,
1796 enum loc_sess_status status,
1797 LocPosTechMask techMask,
1798 bool fromUlp)
1799 {
1800 LOC_LOGD("%s]: fromUlp %u status %u", __func__, fromUlp, status);
1801
1802 // if this event is not called from ULP, then try to call into ULP and return if successfull
1803 if (!fromUlp) {
1804 if (mUlpProxy->reportPosition(ulpLocation, locationExtended,
1805 status, techMask)) {
1806 return;
1807 }
1808 }
1809
1810 struct MsgReportPosition : public LocMsg {
1811 GnssAdapter& mAdapter;
1812 const UlpLocation mUlpLocation;
1813 const GpsLocationExtended mLocationExtended;
1814 loc_sess_status mStatus;
1815 LocPosTechMask mTechMask;
1816 inline MsgReportPosition(GnssAdapter& adapter,
1817 const UlpLocation& ulpLocation,
1818 const GpsLocationExtended& locationExtended,
1819 loc_sess_status status,
1820 LocPosTechMask techMask) :
1821 LocMsg(),
1822 mAdapter(adapter),
1823 mUlpLocation(ulpLocation),
1824 mLocationExtended(locationExtended),
1825 mStatus(status),
1826 mTechMask(techMask) {}
1827 inline virtual void proc() const {
1828 // extract bug report info - this returns true if consumed by systemstatus
1829 SystemStatus* s = LocDualContext::getSystemStatus();
1830 if ((nullptr != s) && (LOC_SESS_SUCCESS == mStatus)){
1831 s->eventPosition(mUlpLocation, mLocationExtended);
1832 }
1833 mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
1834 }
1835 };
1836
1837 sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended, status, techMask));
1838 }
1839
1840 void
reportPosition(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask)1841 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
1842 const GpsLocationExtended& locationExtended,
1843 enum loc_sess_status status,
1844 LocPosTechMask techMask)
1845 {
1846 bool reported = false;
1847 // what's in the if is... (line by line)
1848 // 1. this is a final fix; and
1849 // 1.1 it is a Satellite fix; or
1850 // 1.2 it is a sensor fix
1851 // 2. (must be intermediate fix... implicit)
1852 // 2.1 we accepte intermediate; and
1853 // 2.2 it is NOT the case that
1854 // 2.2.1 there is inaccuracy; and
1855 // 2.2.2 we care about inaccuracy; and
1856 // 2.2.3 the inaccuracy exceeds our tolerance
1857 if ((LOC_SESS_SUCCESS == status &&
1858 ((LOC_POS_TECH_MASK_SATELLITE |
1859 LOC_POS_TECH_MASK_SENSORS |
1860 LOC_POS_TECH_MASK_HYBRID) &
1861 techMask)) ||
1862 (LOC_SESS_INTERMEDIATE == ContextBase::mGps_conf.INTERMEDIATE_POS &&
1863 !((ulpLocation.gpsLocation.flags &
1864 LOC_GPS_LOCATION_HAS_ACCURACY) &&
1865 (ContextBase::mGps_conf.ACCURACY_THRES != 0) &&
1866 (ulpLocation.gpsLocation.accuracy >
1867 ContextBase::mGps_conf.ACCURACY_THRES)))) {
1868 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
1869 mGnssSvIdUsedInPosAvail = true;
1870 mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
1871 }
1872 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1873 if (nullptr != it->second.trackingCb) {
1874 Location location = {};
1875 convertLocation(location, ulpLocation.gpsLocation, locationExtended, techMask);
1876 it->second.trackingCb(location);
1877 }
1878 if (nullptr != it->second.gnssLocationInfoCb) {
1879 GnssLocationInfoNotification locationInfo = {};
1880 convertLocationInfo(locationInfo, locationExtended);
1881 it->second.gnssLocationInfoCb(locationInfo);
1882 }
1883 }
1884 reported = true;
1885 } else {
1886 LOC_LOGI("%s: not reported. Status: %d, techMask: %d, flags %d, accuracy %f",
1887 __func__, (int)status, (int)techMask, (int)ulpLocation.gpsLocation.flags,
1888 (float)ulpLocation.gpsLocation.accuracy);
1889 }
1890
1891 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
1892 uint8_t generate_nmea = (reported && status != LOC_SESS_FAILURE);
1893 std::vector<std::string> nmeaArraystr;
1894 loc_nmea_generate_pos(ulpLocation, locationExtended, generate_nmea, nmeaArraystr);
1895 for (auto sentence : nmeaArraystr) {
1896 reportNmea(sentence.c_str(), sentence.length());
1897 }
1898 }
1899
1900 // Free the allocated memory for rawData
1901 UlpLocation* gp = (UlpLocation*)&(ulpLocation);
1902 if (gp != NULL && gp->rawData != NULL)
1903 {
1904 delete (char*)gp->rawData;
1905 gp->rawData = NULL;
1906 gp->rawDataSize = 0;
1907 }
1908 }
1909
1910 void
reportSvEvent(const GnssSvNotification & svNotify,bool fromUlp)1911 GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
1912 bool fromUlp)
1913 {
1914 LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp);
1915
1916 // if this event is not called from ULP, then try to call into ULP and return if successfull
1917 if (!fromUlp) {
1918 if (mUlpProxy->reportSv(svNotify)) {
1919 return;
1920 }
1921 }
1922
1923 struct MsgReportSv : public LocMsg {
1924 GnssAdapter& mAdapter;
1925 const GnssSvNotification mSvNotify;
1926 inline MsgReportSv(GnssAdapter& adapter,
1927 const GnssSvNotification& svNotify) :
1928 LocMsg(),
1929 mAdapter(adapter),
1930 mSvNotify(svNotify) {}
1931 inline virtual void proc() const {
1932 mAdapter.reportSv((GnssSvNotification&)mSvNotify);
1933 }
1934 };
1935
1936 sendMsg(new MsgReportSv(*this, svNotify));
1937 }
1938
1939 void
reportSv(GnssSvNotification & svNotify)1940 GnssAdapter::reportSv(GnssSvNotification& svNotify)
1941 {
1942 int numSv = svNotify.count;
1943 int16_t gnssSvId = 0;
1944 uint64_t svUsedIdMask = 0;
1945 for (int i=0; i < numSv; i++) {
1946 svUsedIdMask = 0;
1947 gnssSvId = svNotify.gnssSvs[i].svId;
1948 switch (svNotify.gnssSvs[i].type) {
1949 case GNSS_SV_TYPE_GPS:
1950 if (mGnssSvIdUsedInPosAvail) {
1951 svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
1952 }
1953 break;
1954 case GNSS_SV_TYPE_GLONASS:
1955 if (mGnssSvIdUsedInPosAvail) {
1956 svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
1957 }
1958 break;
1959 case GNSS_SV_TYPE_BEIDOU:
1960 if (mGnssSvIdUsedInPosAvail) {
1961 svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
1962 }
1963 break;
1964 case GNSS_SV_TYPE_GALILEO:
1965 if (mGnssSvIdUsedInPosAvail) {
1966 svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
1967 }
1968 break;
1969 case GNSS_SV_TYPE_QZSS:
1970 if (mGnssSvIdUsedInPosAvail) {
1971 svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
1972 }
1973 // QZSS SV id's need to reported as it is to framework, since
1974 // framework expects it as it is. See GnssStatus.java.
1975 // SV id passed to here by LocApi is 1-based.
1976 svNotify.gnssSvs[i].svId += (QZSS_SV_PRN_MIN - 1);
1977 break;
1978 default:
1979 svUsedIdMask = 0;
1980 break;
1981 }
1982
1983 // If SV ID was used in previous position fix, then set USED_IN_FIX
1984 // flag, else clear the USED_IN_FIX flag.
1985 if (svUsedIdMask & (1 << (gnssSvId - 1))) {
1986 svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
1987 }
1988 }
1989
1990 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1991 if (nullptr != it->second.gnssSvCb) {
1992 it->second.gnssSvCb(svNotify);
1993 }
1994 }
1995
1996 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
1997 std::vector<std::string> nmeaArraystr;
1998 loc_nmea_generate_sv(svNotify, nmeaArraystr);
1999 for (auto sentence : nmeaArraystr) {
2000 reportNmea(sentence.c_str(), sentence.length());
2001 }
2002 }
2003
2004 mGnssSvIdUsedInPosAvail = false;
2005 }
2006
2007 void
reportNmeaEvent(const char * nmea,size_t length,bool fromUlp)2008 GnssAdapter::reportNmeaEvent(const char* nmea, size_t length, bool fromUlp)
2009 {
2010 // if this event is not called from ULP, then try to call into ULP and return if successfull
2011 if (!fromUlp && !loc_nmea_is_debug(nmea, length)) {
2012 if (mUlpProxy->reportNmea(nmea, length)) {
2013 return;
2014 }
2015 }
2016
2017 struct MsgReportNmea : public LocMsg {
2018 GnssAdapter& mAdapter;
2019 const char* mNmea;
2020 size_t mLength;
2021 inline MsgReportNmea(GnssAdapter& adapter,
2022 const char* nmea,
2023 size_t length) :
2024 LocMsg(),
2025 mAdapter(adapter),
2026 mNmea(new char[length+1]),
2027 mLength(length) {
2028 strlcpy((char*)mNmea, nmea, length+1);
2029 }
2030 inline virtual ~MsgReportNmea()
2031 {
2032 delete[] mNmea;
2033 }
2034 inline virtual void proc() const {
2035 // extract bug report info - this returns true if consumed by systemstatus
2036 bool ret = false;
2037 SystemStatus* s = LocDualContext::getSystemStatus();
2038 if (nullptr != s) {
2039 ret = s->setNmeaString(mNmea, mLength);
2040 }
2041 if (false == ret) {
2042 // forward NMEA message to upper layer
2043 mAdapter.reportNmea(mNmea, mLength);
2044 }
2045 }
2046 };
2047
2048 sendMsg(new MsgReportNmea(*this, nmea, length));
2049 }
2050
2051 void
reportNmea(const char * nmea,size_t length)2052 GnssAdapter::reportNmea(const char* nmea, size_t length)
2053 {
2054 GnssNmeaNotification nmeaNotification = {};
2055 nmeaNotification.size = sizeof(GnssNmeaNotification);
2056
2057 struct timeval tv;
2058 gettimeofday(&tv, (struct timezone *) NULL);
2059 int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
2060 nmeaNotification.timestamp = now;
2061 nmeaNotification.nmea = nmea;
2062 nmeaNotification.length = length;
2063
2064 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2065 if (nullptr != it->second.gnssNmeaCb) {
2066 it->second.gnssNmeaCb(nmeaNotification);
2067 }
2068 }
2069 }
2070
2071 bool
requestNiNotifyEvent(const GnssNiNotification & notify,const void * data)2072 GnssAdapter::requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* data)
2073 {
2074 LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
2075 "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
2076 __func__, notify.type, notify.timeout, notify.timeoutResponse,
2077 notify.requestor, notify.requestorEncoding,
2078 notify.message, notify.messageEncoding, notify.extras);
2079
2080 struct MsgReportNiNotify : public LocMsg {
2081 GnssAdapter& mAdapter;
2082 const GnssNiNotification mNotify;
2083 const void* mData;
2084 inline MsgReportNiNotify(GnssAdapter& adapter,
2085 const GnssNiNotification& notify,
2086 const void* data) :
2087 LocMsg(),
2088 mAdapter(adapter),
2089 mNotify(notify),
2090 mData(data) {}
2091 inline virtual void proc() const {
2092 mAdapter.requestNiNotify(mNotify, mData);
2093 }
2094 };
2095
2096 sendMsg(new MsgReportNiNotify(*this, notify, data));
2097
2098 return true;
2099 }
2100
niThreadProc(void * args)2101 static void* niThreadProc(void *args)
2102 {
2103 NiSession* pSession = (NiSession*)args;
2104 int rc = 0; /* return code from pthread calls */
2105
2106 struct timeval present_time;
2107 struct timespec expire_time;
2108
2109 pthread_mutex_lock(&pSession->tLock);
2110 /* Calculate absolute expire time */
2111 gettimeofday(&present_time, NULL);
2112 expire_time.tv_sec = present_time.tv_sec + pSession->respTimeLeft;
2113 expire_time.tv_nsec = present_time.tv_usec * 1000;
2114 LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
2115 __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
2116
2117 while (!pSession->respRecvd) {
2118 rc = pthread_cond_timedwait(&pSession->tCond,
2119 &pSession->tLock,
2120 &expire_time);
2121 if (rc == ETIMEDOUT) {
2122 pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
2123 LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
2124 __func__, rc);
2125 break;
2126 }
2127 }
2128 LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
2129 "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
2130 pSession->respRecvd = false; /* Reset the user response flag for the next session*/
2131
2132 // adding this check to support modem restart, in which case, we need the thread
2133 // to exit without calling sending data. We made sure that rawRequest is NULL in
2134 // loc_eng_ni_reset_on_engine_restart()
2135 GnssAdapter* adapter = pSession->adapter;
2136 GnssNiResponse resp;
2137 void* rawRequest = NULL;
2138 bool sendResponse = false;
2139
2140 if (NULL != pSession->rawRequest) {
2141 if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
2142 resp = pSession->resp;
2143 rawRequest = pSession->rawRequest;
2144 sendResponse = true;
2145 } else {
2146 free(pSession->rawRequest);
2147 }
2148 pSession->rawRequest = NULL;
2149 }
2150 pthread_mutex_unlock(&pSession->tLock);
2151
2152 pSession->respTimeLeft = 0;
2153 pSession->reqID = 0;
2154
2155 if (sendResponse) {
2156 adapter->gnssNiResponseCommand(resp, rawRequest);
2157 }
2158
2159 return NULL;
2160 }
2161
2162 bool
requestNiNotify(const GnssNiNotification & notify,const void * data)2163 GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data)
2164 {
2165 NiSession* pSession = NULL;
2166 gnssNiCallback gnssNiCb = nullptr;
2167
2168 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2169 if (nullptr != it->second.gnssNiCb) {
2170 gnssNiCb = it->second.gnssNiCb;
2171 break;
2172 }
2173 }
2174 if (nullptr == gnssNiCb) {
2175 EXIT_LOG(%s, "no clients with gnssNiCb.");
2176 return false;
2177 }
2178
2179 if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
2180 if (NULL != mNiData.sessionEs.rawRequest) {
2181 LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
2182 __func__, notify.type);
2183 if (NULL != data) {
2184 free((void*)data);
2185 }
2186 } else {
2187 pSession = &mNiData.sessionEs;
2188 }
2189 } else {
2190 if (NULL != mNiData.session.rawRequest ||
2191 NULL != mNiData.sessionEs.rawRequest) {
2192 LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
2193 __func__, notify.type);
2194 if (NULL != data) {
2195 free((void*)data);
2196 }
2197 } else {
2198 pSession = &mNiData.session;
2199 }
2200 }
2201
2202 if (pSession) {
2203 /* Save request */
2204 pSession->rawRequest = (void*)data;
2205 pSession->reqID = ++mNiData.reqIDCounter;
2206 pSession->adapter = this;
2207
2208 int sessionId = pSession->reqID;
2209
2210 /* For robustness, spawn a thread at this point to timeout to clear up the notification
2211 * status, even though the OEM layer in java does not do so.
2212 **/
2213 pSession->respTimeLeft =
2214 5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
2215
2216 int rc = 0;
2217 rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
2218 if (rc) {
2219 LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
2220 }
2221 rc = pthread_detach(pSession->thread);
2222 if (rc) {
2223 LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
2224 }
2225
2226 if (nullptr != gnssNiCb) {
2227 gnssNiCb(sessionId, notify);
2228 }
2229 }
2230
2231 return true;
2232 }
2233
2234 void
reportGnssMeasurementDataEvent(const GnssMeasurementsNotification & measurementsNotify)2235 GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurementsNotify)
2236 {
2237 LOC_LOGD("%s]: ", __func__);
2238
2239 struct MsgReportGnssMeasurementData : public LocMsg {
2240 GnssAdapter& mAdapter;
2241 const GnssMeasurementsNotification mMeasurementsNotify;
2242 inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
2243 const GnssMeasurementsNotification& measurementsNotify) :
2244 LocMsg(),
2245 mAdapter(adapter),
2246 mMeasurementsNotify(measurementsNotify) {}
2247 inline virtual void proc() const {
2248 mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
2249 }
2250 };
2251
2252 sendMsg(new MsgReportGnssMeasurementData(*this, measurementsNotify));
2253 }
2254
2255 void
reportGnssMeasurementData(const GnssMeasurementsNotification & measurementsNotify)2256 GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurementsNotify)
2257 {
2258 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2259 if (nullptr != it->second.gnssMeasurementsCb) {
2260 it->second.gnssMeasurementsCb(measurementsNotify);
2261 }
2262 }
2263 }
2264
2265 void
reportSvMeasurementEvent(GnssSvMeasurementSet & svMeasurementSet)2266 GnssAdapter::reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet)
2267 {
2268 LOC_LOGD("%s]: ", __func__);
2269
2270 // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
2271 mUlpProxy->reportSvMeasurement(svMeasurementSet);
2272 }
2273
2274 void
reportSvPolynomialEvent(GnssSvPolynomial & svPolynomial)2275 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
2276 {
2277 LOC_LOGD("%s]: ", __func__);
2278
2279 // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
2280 mUlpProxy->reportSvPolynomial(svPolynomial);
2281 }
2282
2283 /* INIT LOC AGPS MANAGER */
initAgpsCommand(void * statusV4Cb)2284 void GnssAdapter::initAgpsCommand(void* statusV4Cb){
2285
2286 LOC_LOGI("GnssAdapter::initAgpsCommand");
2287
2288 /* Set ATL open/close callbacks */
2289 AgpsAtlOpenStatusCb atlOpenStatusCb =
2290 [this](int handle, int isSuccess, char* apn,
2291 AGpsBearerType bearerType, AGpsExtType agpsType) {
2292
2293 mLocApi->atlOpenStatus(
2294 handle, isSuccess, apn, bearerType, agpsType);
2295 };
2296 AgpsAtlCloseStatusCb atlCloseStatusCb =
2297 [this](int handle, int isSuccess) {
2298
2299 mLocApi->atlCloseStatus(handle, isSuccess);
2300 };
2301
2302 /* Register DS Client APIs */
2303 AgpsDSClientInitFn dsClientInitFn =
2304 [this](bool isDueToSSR) {
2305
2306 return mLocApi->initDataServiceClient(isDueToSSR);
2307 };
2308
2309 AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn =
2310 [this] {
2311
2312 return mLocApi->openAndStartDataCall();
2313 };
2314
2315 AgpsDSClientStopDataCallFn dsClientStopDataCallFn =
2316 [this] {
2317
2318 mLocApi->stopDataCall();
2319 };
2320
2321 AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn =
2322 [this] {
2323
2324 mLocApi->closeDataCall();
2325 };
2326
2327 AgpsDSClientReleaseFn dsClientReleaseFn =
2328 [this] {
2329
2330 mLocApi->releaseDataServiceClient();
2331 };
2332
2333 /* Send Msg function */
2334 SendMsgToAdapterMsgQueueFn sendMsgFn =
2335 [this](LocMsg* msg) {
2336
2337 sendMsg(msg);
2338 };
2339
2340 /* Message to initialize AGPS module */
2341 struct AgpsMsgInit: public LocMsg {
2342
2343 AgpsManager* mAgpsManager;
2344
2345 AgpsFrameworkInterface::AgnssStatusIpV4Cb mFrameworkStatusV4Cb;
2346
2347 AgpsAtlOpenStatusCb mAtlOpenStatusCb;
2348 AgpsAtlCloseStatusCb mAtlCloseStatusCb;
2349
2350 AgpsDSClientInitFn mDSClientInitFn;
2351 AgpsDSClientOpenAndStartDataCallFn mDSClientOpenAndStartDataCallFn;
2352 AgpsDSClientStopDataCallFn mDSClientStopDataCallFn;
2353 AgpsDSClientCloseDataCallFn mDSClientCloseDataCallFn;
2354 AgpsDSClientReleaseFn mDSClientReleaseFn;
2355
2356 SendMsgToAdapterMsgQueueFn mSendMsgFn;
2357 GnssAdapter& mAdapter;
2358
2359 inline AgpsMsgInit(AgpsManager* agpsManager,
2360 AgpsFrameworkInterface::AgnssStatusIpV4Cb frameworkStatusV4Cb,
2361 AgpsAtlOpenStatusCb atlOpenStatusCb,
2362 AgpsAtlCloseStatusCb atlCloseStatusCb,
2363 AgpsDSClientInitFn dsClientInitFn,
2364 AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn,
2365 AgpsDSClientStopDataCallFn dsClientStopDataCallFn,
2366 AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn,
2367 AgpsDSClientReleaseFn dsClientReleaseFn,
2368 SendMsgToAdapterMsgQueueFn sendMsgFn,
2369 GnssAdapter& adapter) :
2370 LocMsg(), mAgpsManager(agpsManager), mFrameworkStatusV4Cb(
2371 frameworkStatusV4Cb), mAtlOpenStatusCb(atlOpenStatusCb), mAtlCloseStatusCb(
2372 atlCloseStatusCb), mDSClientInitFn(dsClientInitFn), mDSClientOpenAndStartDataCallFn(
2373 dsClientOpenAndStartDataCallFn), mDSClientStopDataCallFn(
2374 dsClientStopDataCallFn), mDSClientCloseDataCallFn(
2375 dsClientCloseDataCallFn), mDSClientReleaseFn(
2376 dsClientReleaseFn), mSendMsgFn(sendMsgFn),
2377 mAdapter(adapter) {
2378
2379 LOC_LOGV("AgpsMsgInit");
2380 }
2381
2382 inline virtual void proc() const {
2383
2384 LOC_LOGV("AgpsMsgInit::proc()");
2385
2386 mAgpsManager->registerCallbacks(mFrameworkStatusV4Cb, mAtlOpenStatusCb,
2387 mAtlCloseStatusCb, mDSClientInitFn,
2388 mDSClientOpenAndStartDataCallFn, mDSClientStopDataCallFn,
2389 mDSClientCloseDataCallFn, mDSClientReleaseFn, mSendMsgFn);
2390
2391 mAgpsManager->createAgpsStateMachines();
2392
2393 /* Register for AGPS event mask */
2394 mAdapter.updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
2395 LOC_REGISTRATION_MASK_ENABLED);
2396 }
2397 };
2398
2399 /* Send message to initialize AGPS Manager */
2400 sendMsg(new AgpsMsgInit(
2401 &mAgpsManager,
2402 (AgpsFrameworkInterface::AgnssStatusIpV4Cb)statusV4Cb,
2403 atlOpenStatusCb, atlCloseStatusCb,
2404 dsClientInitFn, dsClientOpenAndStartDataCallFn,
2405 dsClientStopDataCallFn, dsClientCloseDataCallFn,
2406 dsClientReleaseFn,
2407 sendMsgFn,
2408 *this));
2409 }
2410
2411 /* GnssAdapter::requestATL
2412 * Method triggered in QMI thread as part of handling below message:
2413 * eQMI_LOC_SERVER_REQUEST_OPEN_V02
2414 * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
2415 * eQMI_LOC_WWAN_TYPE_INTERNET_V02
2416 * eQMI_LOC_WWAN_TYPE_AGNSS_V02 */
requestATL(int connHandle,LocAGpsType agpsType)2417 bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType){
2418
2419 LOC_LOGI("GnssAdapter::requestATL");
2420
2421 sendMsg( new AgpsMsgRequestATL(
2422 &mAgpsManager, connHandle, (AGpsExtType)agpsType));
2423
2424 return true;
2425 }
2426
2427 /* GnssAdapter::requestSuplES
2428 * Method triggered in QMI thread as part of handling below message:
2429 * eQMI_LOC_SERVER_REQUEST_OPEN_V02
2430 * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
2431 * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
requestSuplES(int connHandle)2432 bool GnssAdapter::requestSuplES(int connHandle){
2433
2434 LOC_LOGI("GnssAdapter::requestSuplES");
2435
2436 sendMsg( new AgpsMsgRequestATL(
2437 &mAgpsManager, connHandle, LOC_AGPS_TYPE_SUPL_ES));
2438
2439 return true;
2440 }
2441
2442 /* GnssAdapter::releaseATL
2443 * Method triggered in QMI thread as part of handling below message:
2444 * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
2445 * Triggers teardown of an existing AGPS call */
releaseATL(int connHandle)2446 bool GnssAdapter::releaseATL(int connHandle){
2447
2448 LOC_LOGI("GnssAdapter::releaseATL");
2449
2450 /* Release SUPL/INTERNET/SUPL_ES ATL */
2451 struct AgpsMsgReleaseATL: public LocMsg {
2452
2453 AgpsManager* mAgpsManager;
2454 int mConnHandle;
2455
2456 inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
2457 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
2458
2459 LOC_LOGV("AgpsMsgReleaseATL");
2460 }
2461
2462 inline virtual void proc() const {
2463
2464 LOC_LOGV("AgpsMsgReleaseATL::proc()");
2465 mAgpsManager->releaseATL(mConnHandle);
2466 }
2467 };
2468
2469 sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
2470
2471 return true;
2472 }
2473
2474 /* GnssAdapter::reportDataCallOpened
2475 * DS Client data call opened successfully.
2476 * Send message to AGPS Manager to handle. */
reportDataCallOpened()2477 bool GnssAdapter::reportDataCallOpened(){
2478
2479 LOC_LOGI("GnssAdapter::reportDataCallOpened");
2480
2481 struct AgpsMsgSuplEsOpened: public LocMsg {
2482
2483 AgpsManager* mAgpsManager;
2484
2485 inline AgpsMsgSuplEsOpened(AgpsManager* agpsManager) :
2486 LocMsg(), mAgpsManager(agpsManager) {
2487
2488 LOC_LOGV("AgpsMsgSuplEsOpened");
2489 }
2490
2491 inline virtual void proc() const {
2492
2493 LOC_LOGV("AgpsMsgSuplEsOpened::proc()");
2494 mAgpsManager->reportDataCallOpened();
2495 }
2496 };
2497
2498 sendMsg( new AgpsMsgSuplEsOpened(&mAgpsManager));
2499
2500 return true;
2501 }
2502
2503 /* GnssAdapter::reportDataCallClosed
2504 * DS Client data call closed.
2505 * Send message to AGPS Manager to handle. */
reportDataCallClosed()2506 bool GnssAdapter::reportDataCallClosed(){
2507
2508 LOC_LOGI("GnssAdapter::reportDataCallClosed");
2509
2510 struct AgpsMsgSuplEsClosed: public LocMsg {
2511
2512 AgpsManager* mAgpsManager;
2513
2514 inline AgpsMsgSuplEsClosed(AgpsManager* agpsManager) :
2515 LocMsg(), mAgpsManager(agpsManager) {
2516
2517 LOC_LOGV("AgpsMsgSuplEsClosed");
2518 }
2519
2520 inline virtual void proc() const {
2521
2522 LOC_LOGV("AgpsMsgSuplEsClosed::proc()");
2523 mAgpsManager->reportDataCallClosed();
2524 }
2525 };
2526
2527 sendMsg( new AgpsMsgSuplEsClosed(&mAgpsManager));
2528
2529 return true;
2530 }
2531
dataConnOpenCommand(AGpsExtType agpsType,const char * apnName,int apnLen,LocApnIpType ipType)2532 void GnssAdapter::dataConnOpenCommand(
2533 AGpsExtType agpsType,
2534 const char* apnName, int apnLen, LocApnIpType ipType){
2535
2536 LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
2537
2538 struct AgpsMsgAtlOpenSuccess: public LocMsg {
2539
2540 AgpsManager* mAgpsManager;
2541 AGpsExtType mAgpsType;
2542 char* mApnName;
2543 int mApnLen;
2544 LocApnIpType mIpType;
2545
2546 inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
2547 const char* apnName, int apnLen, LocApnIpType ipType) :
2548 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
2549 new char[apnLen + 1]), mApnLen(apnLen), mIpType(ipType) {
2550
2551 LOC_LOGV("AgpsMsgAtlOpenSuccess");
2552 if (mApnName == nullptr) {
2553 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
2554 // Reporting the failure here
2555 mAgpsManager->reportAtlClosed(mAgpsType);
2556 return;
2557 }
2558 memcpy(mApnName, apnName, apnLen);
2559 mApnName[apnLen] = 0;
2560 }
2561
2562 inline ~AgpsMsgAtlOpenSuccess() {
2563 delete[] mApnName;
2564 }
2565
2566 inline virtual void proc() const {
2567
2568 LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
2569 mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen,
2570 mIpType);
2571 }
2572 };
2573
2574 // Added inital length checks for apnlen check to avoid security issues
2575 // In case of failure reporting the same
2576 if (NULL == apnName || apnLen <= 0 || apnLen > MAX_APN_LEN ||
2577 (strlen(apnName) != (unsigned)apnLen)) {
2578 LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__);
2579 mAgpsManager.reportAtlClosed(agpsType);
2580 } else {
2581 sendMsg( new AgpsMsgAtlOpenSuccess(
2582 &mAgpsManager, agpsType, apnName, apnLen, bearerType));
2583 }
2584 }
2585
dataConnClosedCommand(AGpsExtType agpsType)2586 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
2587
2588 LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
2589
2590 struct AgpsMsgAtlClosed: public LocMsg {
2591
2592 AgpsManager* mAgpsManager;
2593 AGpsExtType mAgpsType;
2594
2595 inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
2596 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
2597
2598 LOC_LOGV("AgpsMsgAtlClosed");
2599 }
2600
2601 inline virtual void proc() const {
2602
2603 LOC_LOGV("AgpsMsgAtlClosed::proc()");
2604 mAgpsManager->reportAtlClosed(mAgpsType);
2605 }
2606 };
2607
2608 sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
2609 }
2610
dataConnFailedCommand(AGpsExtType agpsType)2611 void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
2612
2613 LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
2614
2615 struct AgpsMsgAtlOpenFailed: public LocMsg {
2616
2617 AgpsManager* mAgpsManager;
2618 AGpsExtType mAgpsType;
2619
2620 inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
2621 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
2622
2623 LOC_LOGV("AgpsMsgAtlOpenFailed");
2624 }
2625
2626 inline virtual void proc() const {
2627
2628 LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
2629 mAgpsManager->reportAtlOpenFailed(mAgpsType);
2630 }
2631 };
2632
2633 sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
2634 }
2635
convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo> & out,const GnssSvType & in_constellation,const SystemStatusReports & in)2636 void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
2637 const GnssSvType& in_constellation,
2638 const SystemStatusReports& in)
2639 {
2640 uint64_t sv_mask = 0ULL;
2641 uint32_t svid_min = 0;
2642 uint32_t svid_num = 0;
2643 uint32_t svid_idx = 0;
2644
2645 uint64_t eph_health_good_mask = 0ULL;
2646 uint64_t eph_health_bad_mask = 0ULL;
2647 uint64_t server_perdiction_available_mask = 0ULL;
2648 float server_perdiction_age = 0.0f;
2649
2650 // set constellationi based parameters
2651 switch (in_constellation) {
2652 case GNSS_SV_TYPE_GPS:
2653 svid_min = GNSS_BUGREPORT_GPS_MIN;
2654 svid_num = GPS_NUM;
2655 svid_idx = 0;
2656 if (!in.mSvHealth.empty()) {
2657 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
2658 eph_health_bad_mask = in.mSvHealth.back().mGpsBadMask;
2659 }
2660 if (!in.mXtra.empty()) {
2661 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
2662 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
2663 }
2664 break;
2665 case GNSS_SV_TYPE_GLONASS:
2666 svid_min = GNSS_BUGREPORT_GLO_MIN;
2667 svid_num = GLO_NUM;
2668 svid_idx = GPS_NUM;
2669 if (!in.mSvHealth.empty()) {
2670 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
2671 eph_health_bad_mask = in.mSvHealth.back().mGloBadMask;
2672 }
2673 if (!in.mXtra.empty()) {
2674 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
2675 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
2676 }
2677 break;
2678 case GNSS_SV_TYPE_QZSS:
2679 svid_min = GNSS_BUGREPORT_QZSS_MIN;
2680 svid_num = QZSS_NUM;
2681 svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
2682 if (!in.mSvHealth.empty()) {
2683 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
2684 eph_health_bad_mask = in.mSvHealth.back().mQzssBadMask;
2685 }
2686 if (!in.mXtra.empty()) {
2687 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
2688 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
2689 }
2690 break;
2691 case GNSS_SV_TYPE_BEIDOU:
2692 svid_min = GNSS_BUGREPORT_BDS_MIN;
2693 svid_num = BDS_NUM;
2694 svid_idx = GPS_NUM+GLO_NUM;
2695 if (!in.mSvHealth.empty()) {
2696 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
2697 eph_health_bad_mask = in.mSvHealth.back().mBdsBadMask;
2698 }
2699 if (!in.mXtra.empty()) {
2700 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
2701 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
2702 }
2703 break;
2704 case GNSS_SV_TYPE_GALILEO:
2705 svid_min = GNSS_BUGREPORT_GAL_MIN;
2706 svid_num = GAL_NUM;
2707 svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
2708 if (!in.mSvHealth.empty()) {
2709 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
2710 eph_health_bad_mask = in.mSvHealth.back().mGalBadMask;
2711 }
2712 if (!in.mXtra.empty()) {
2713 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
2714 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
2715 }
2716 break;
2717 default:
2718 return;
2719 }
2720
2721 // extract each sv info from systemstatus report
2722 for(uint32_t i=0; i<svid_num; i++) {
2723
2724 GnssDebugSatelliteInfo s = {};
2725 s.size = sizeof(s);
2726 s.svid = i + svid_min;
2727 s.constellation = in_constellation;
2728
2729 if (!in.mNavData.empty()) {
2730 s.mEphemerisType = in.mNavData.back().mNav[svid_idx+i].mType;
2731 s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
2732 }
2733 else {
2734 s.mEphemerisType = GNSS_EPH_TYPE_UNKNOWN;
2735 s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
2736 }
2737
2738 sv_mask = 0x1ULL << i;
2739 if (eph_health_good_mask & sv_mask) {
2740 s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
2741 }
2742 else if (eph_health_bad_mask & sv_mask) {
2743 s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
2744 }
2745 else {
2746 s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
2747 }
2748
2749 if (!in.mNavData.empty()) {
2750 s.ephemerisAgeSeconds =
2751 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
2752 }
2753 else {
2754 s.ephemerisAgeSeconds = 0.0f;
2755 }
2756
2757 if (server_perdiction_available_mask & sv_mask) {
2758 s.serverPredictionIsAvailable = true;
2759 }
2760 else {
2761 s.serverPredictionIsAvailable = false;
2762 }
2763
2764 s.serverPredictionAgeSeconds = server_perdiction_age;
2765 out.push_back(s);
2766 }
2767
2768 return;
2769 }
2770
getDebugReport(GnssDebugReport & r)2771 bool GnssAdapter::getDebugReport(GnssDebugReport& r)
2772 {
2773 LOC_LOGD("%s]: ", __func__);
2774
2775 SystemStatus* systemstatus = LocDualContext::getSystemStatus();
2776 if (nullptr == systemstatus) {
2777 return false;
2778 }
2779
2780 SystemStatusReports reports = {};
2781 systemstatus->getReport(reports, true);
2782
2783 r.size = sizeof(r);
2784
2785 // location block
2786 r.mLocation.size = sizeof(r.mLocation);
2787 if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
2788 r.mLocation.mValid = true;
2789 r.mLocation.mLocation.latitude =
2790 reports.mLocation.back().mLocation.gpsLocation.latitude;
2791 r.mLocation.mLocation.longitude =
2792 reports.mLocation.back().mLocation.gpsLocation.longitude;
2793 r.mLocation.mLocation.altitude =
2794 reports.mLocation.back().mLocation.gpsLocation.altitude;
2795 r.mLocation.mLocation.speed =
2796 (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
2797 r.mLocation.mLocation.bearing =
2798 (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
2799 r.mLocation.mLocation.accuracy =
2800 (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
2801
2802 r.mLocation.verticalAccuracyMeters =
2803 reports.mLocation.back().mLocationEx.vert_unc;
2804 r.mLocation.speedAccuracyMetersPerSecond =
2805 reports.mLocation.back().mLocationEx.speed_unc;
2806 r.mLocation.bearingAccuracyDegrees =
2807 reports.mLocation.back().mLocationEx.bearing_unc;
2808
2809 r.mLocation.mUtcReported =
2810 reports.mLocation.back().mUtcReported;
2811 }
2812 else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
2813 r.mLocation.mValid = true;
2814 r.mLocation.mLocation.latitude =
2815 (double)(reports.mBestPosition.back().mBestLat);
2816 r.mLocation.mLocation.longitude =
2817 (double)(reports.mBestPosition.back().mBestLon);
2818 r.mLocation.mLocation.altitude =
2819 reports.mBestPosition.back().mBestAlt;
2820
2821 r.mLocation.mLocation.timestamp =
2822 reports.mBestPosition.back().mUtcReported.tv_sec * 1000ULL +
2823 reports.mBestPosition.back().mUtcReported.tv_nsec / 1000000ULL;
2824 }
2825 else {
2826 r.mLocation.mValid = false;
2827 }
2828
2829 if (r.mLocation.mValid) {
2830 LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
2831 r.mLocation.mLocation.latitude,
2832 r.mLocation.mLocation.longitude,
2833 r.mLocation.mLocation.altitude,
2834 r.mLocation.mLocation.speed);
2835 }
2836
2837 // time block
2838 r.mTime.size = sizeof(r.mTime);
2839 if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
2840 r.mTime.mValid = true;
2841 r.mTime.timeEstimate =
2842 (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
2843 GNSS_UTC_TIME_OFFSET)*24*60*60 -
2844 (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
2845 (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
2846
2847 r.mTime.timeUncertaintyNs =
2848 (float)((reports.mTimeAndClock.back().mTimeUnc +
2849 reports.mTimeAndClock.back().mLeapSecUnc)*1000);
2850 r.mTime.frequencyUncertaintyNsPerSec =
2851 (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
2852 LOC_LOGV("getDebugReport - timeestimate=%ld unc=%f frequnc=%f",
2853 r.mTime.timeEstimate,
2854 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
2855 }
2856 else {
2857 r.mTime.mValid = false;
2858 }
2859
2860 // satellite info block
2861 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
2862 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
2863 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
2864 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
2865 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
2866 LOC_LOGV("getDebugReport - satellite=%lu", r.mSatelliteInfo.size());
2867
2868 return true;
2869 }