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