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