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