1 /* Copyright (c) 2017-2018, 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_NDEBUG 0
30 #define LOG_TAG "LocSvc_GnssAdapter"
31
32 #include <inttypes.h>
33 #include <sys/stat.h>
34 #include <errno.h>
35 #include <ctype.h>
36 #include <cutils/properties.h>
37 #include <math.h>
38 #include <arpa/inet.h>
39 #include <netinet/in.h>
40 #include <netdb.h>
41 #include <GnssAdapter.h>
42 #include <string>
43 #include <loc_log.h>
44 #include <loc_nmea.h>
45 #include <Agps.h>
46 #include <SystemStatus.h>
47
48 #include <vector>
49
50 #define RAD2DEG (180.0 / M_PI)
51
52 using namespace loc_core;
53
54 /* Method to fetch status cb from loc_net_iface library */
55 typedef AgpsCbInfo& (*LocAgpsGetAgpsCbInfo)(LocAgpsOpenResultCb openResultCb,
56 LocAgpsCloseResultCb closeResultCb, void* userDataPtr);
57
58 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
59 AGpsBearerType bearerType, void* userDataPtr);
60 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr);
61
GnssAdapter()62 GnssAdapter::GnssAdapter() :
63 LocAdapterBase(0,
64 LocDualContext::getLocFgContext(NULL,
65 NULL,
66 LocDualContext::mLocationHalName,
67 false), true, nullptr),
68 mUlpProxy(new UlpProxyBase()),
69 mUlpPositionMode(),
70 mGnssSvIdUsedInPosition(),
71 mGnssSvIdUsedInPosAvail(false),
72 mControlCallbacks(),
73 mPowerVoteId(0),
74 mNmeaMask(0),
75 mGnssSvIdConfig(),
76 mGnssSvTypeConfig(),
77 mGnssSvTypeConfigCb(nullptr),
78 mNiData(),
79 mAgpsManager(),
80 mAgpsCbInfo(),
81 mOdcpiRequestCb(nullptr),
82 mOdcpiRequestActive(false),
83 mOdcpiTimer(this),
84 mOdcpiRequest(),
85 mSystemStatus(SystemStatus::getInstance(mMsgTask)),
86 mServerUrl(":"),
87 mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask)
88 {
89 LOC_LOGD("%s]: Constructor %p", __func__, this);
90 mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID;
91
92 pthread_condattr_t condAttr;
93 pthread_condattr_init(&condAttr);
94 pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
95 pthread_cond_init(&mNiData.session.tCond, &condAttr);
96 pthread_cond_init(&mNiData.sessionEs.tCond, &condAttr);
97 pthread_condattr_destroy(&condAttr);
98
99 /* Set ATL open/close callbacks */
100 AgpsAtlOpenStatusCb atlOpenStatusCb =
101 [this](int handle, int isSuccess, char* apn,
102 AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) {
103
104 mLocApi->atlOpenStatus(
105 handle, isSuccess, apn, bearerType, agpsType, mask);
106 };
107 AgpsAtlCloseStatusCb atlCloseStatusCb =
108 [this](int handle, int isSuccess) {
109
110 mLocApi->atlCloseStatus(handle, isSuccess);
111 };
112
113 /* Register DS Client APIs */
114 AgpsDSClientInitFn dsClientInitFn =
115 [this](bool isDueToSSR) {
116
117 return mLocApi->initDataServiceClient(isDueToSSR);
118 };
119
120 AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn =
121 [this] {
122
123 return mLocApi->openAndStartDataCall();
124 };
125
126 AgpsDSClientStopDataCallFn dsClientStopDataCallFn =
127 [this] {
128
129 mLocApi->stopDataCall();
130 };
131
132 AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn =
133 [this] {
134
135 mLocApi->closeDataCall();
136 };
137
138 AgpsDSClientReleaseFn dsClientReleaseFn =
139 [this] {
140
141 mLocApi->releaseDataServiceClient();
142 };
143
144 /* Send Msg function */
145 SendMsgToAdapterMsgQueueFn sendMsgFn =
146 [this](LocMsg* msg) {
147
148 sendMsg(msg);
149 };
150 mAgpsManager.registerATLCallbacks(atlOpenStatusCb, atlCloseStatusCb,
151 dsClientInitFn, dsClientOpenAndStartDataCallFn, dsClientStopDataCallFn,
152 dsClientCloseDataCallFn, dsClientReleaseFn, sendMsgFn);
153
154 readConfigCommand();
155 setConfigCommand();
156 initDefaultAgpsCommand();
157 }
158
159 void
setControlCallbacksCommand(LocationControlCallbacks & controlCallbacks)160 GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
161 {
162 struct MsgSetControlCallbacks : public LocMsg {
163 GnssAdapter& mAdapter;
164 const LocationControlCallbacks mControlCallbacks;
165 inline MsgSetControlCallbacks(GnssAdapter& adapter,
166 LocationControlCallbacks& controlCallbacks) :
167 LocMsg(),
168 mAdapter(adapter),
169 mControlCallbacks(controlCallbacks) {}
170 inline virtual void proc() const {
171 mAdapter.setControlCallbacks(mControlCallbacks);
172 }
173 };
174
175 sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
176 }
177
178 void
convertOptions(LocPosMode & out,const TrackingOptions & trackingOptions)179 GnssAdapter::convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions)
180 {
181 switch (trackingOptions.mode) {
182 case GNSS_SUPL_MODE_MSB:
183 out.mode = LOC_POSITION_MODE_MS_BASED;
184 break;
185 case GNSS_SUPL_MODE_MSA:
186 out.mode = LOC_POSITION_MODE_MS_ASSISTED;
187 break;
188 default:
189 out.mode = LOC_POSITION_MODE_STANDALONE;
190 break;
191 }
192 out.share_position = true;
193 out.min_interval = trackingOptions.minInterval;
194 out.powerMode = trackingOptions.powerMode;
195 out.timeBetweenMeasurements = trackingOptions.tbm;
196 }
197
198 void
convertLocation(Location & out,const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,const LocPosTechMask techMask)199 GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation,
200 const GpsLocationExtended& locationExtended,
201 const LocPosTechMask techMask)
202 {
203 memset(&out, 0, sizeof(Location));
204 out.size = sizeof(Location);
205 if (LOC_GPS_LOCATION_HAS_LAT_LONG & ulpLocation.gpsLocation.flags) {
206 out.flags |= LOCATION_HAS_LAT_LONG_BIT;
207 out.latitude = ulpLocation.gpsLocation.latitude;
208 out.longitude = ulpLocation.gpsLocation.longitude;
209 }
210 if (LOC_GPS_LOCATION_HAS_ALTITUDE & ulpLocation.gpsLocation.flags) {
211 out.flags |= LOCATION_HAS_ALTITUDE_BIT;
212 out.altitude = ulpLocation.gpsLocation.altitude;
213 }
214 if (LOC_GPS_LOCATION_HAS_SPEED & ulpLocation.gpsLocation.flags) {
215 out.flags |= LOCATION_HAS_SPEED_BIT;
216 out.speed = ulpLocation.gpsLocation.speed;
217 }
218 if (LOC_GPS_LOCATION_HAS_BEARING & ulpLocation.gpsLocation.flags) {
219 out.flags |= LOCATION_HAS_BEARING_BIT;
220 out.bearing = ulpLocation.gpsLocation.bearing;
221 }
222 if (LOC_GPS_LOCATION_HAS_ACCURACY & ulpLocation.gpsLocation.flags) {
223 out.flags |= LOCATION_HAS_ACCURACY_BIT;
224 out.accuracy = ulpLocation.gpsLocation.accuracy;
225 }
226 if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
227 out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
228 out.verticalAccuracy = locationExtended.vert_unc;
229 }
230 if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
231 out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
232 out.speedAccuracy = locationExtended.speed_unc;
233 }
234 if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
235 out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
236 out.bearingAccuracy = locationExtended.bearing_unc;
237 }
238 out.timestamp = ulpLocation.gpsLocation.timestamp;
239 if (LOC_POS_TECH_MASK_SATELLITE & techMask) {
240 out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
241 }
242 if (LOC_POS_TECH_MASK_CELLID & techMask) {
243 out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
244 }
245 if (LOC_POS_TECH_MASK_WIFI & techMask) {
246 out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
247 }
248 if (LOC_POS_TECH_MASK_SENSORS & techMask) {
249 out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
250 }
251 }
252
253 void
convertLocationInfo(GnssLocationInfoNotification & out,const GpsLocationExtended & locationExtended)254 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
255 const GpsLocationExtended& locationExtended)
256 {
257 out.size = sizeof(GnssLocationInfoNotification);
258 if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
259 out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
260 out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
261 }
262 if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
263 out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
264 out.pdop = locationExtended.pdop;
265 out.hdop = locationExtended.hdop;
266 out.vdop = locationExtended.vdop;
267 }
268 if (GPS_LOCATION_EXTENDED_HAS_EXT_DOP & locationExtended.flags) {
269 out.flags |= GNSS_LOCATION_INFO_EXT_DOP_BIT;
270 out.gdop = locationExtended.extDOP.GDOP;
271 out.tdop = locationExtended.extDOP.TDOP;
272 }
273 if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
274 out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
275 out.magneticDeviation = locationExtended.magneticDeviation;
276 }
277 if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
278 out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
279 switch (locationExtended.horizontal_reliability) {
280 case LOC_RELIABILITY_VERY_LOW:
281 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
282 break;
283 case LOC_RELIABILITY_LOW:
284 out.horReliability = LOCATION_RELIABILITY_LOW;
285 break;
286 case LOC_RELIABILITY_MEDIUM:
287 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
288 break;
289 case LOC_RELIABILITY_HIGH:
290 out.horReliability = LOCATION_RELIABILITY_HIGH;
291 break;
292 default:
293 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
294 break;
295 }
296 }
297 if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
298 out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
299 switch (locationExtended.vertical_reliability) {
300 case LOC_RELIABILITY_VERY_LOW:
301 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
302 break;
303 case LOC_RELIABILITY_LOW:
304 out.verReliability = LOCATION_RELIABILITY_LOW;
305 break;
306 case LOC_RELIABILITY_MEDIUM:
307 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
308 break;
309 case LOC_RELIABILITY_HIGH:
310 out.verReliability = LOCATION_RELIABILITY_HIGH;
311 break;
312 default:
313 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
314 break;
315 }
316 }
317 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
318 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
319 out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
320 }
321 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
322 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
323 out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
324 }
325 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
326 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
327 out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
328 }
329 if (GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA & locationExtended.flags) {
330 out.flags |= GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT;
331 out.svUsedInPosition.gpsSvUsedIdsMask =
332 locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask;
333 out.svUsedInPosition.gloSvUsedIdsMask =
334 locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask;
335 out.svUsedInPosition.galSvUsedIdsMask =
336 locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask;
337 out.svUsedInPosition.bdsSvUsedIdsMask =
338 locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask;
339 out.svUsedInPosition.qzssSvUsedIdsMask =
340 locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask;
341 }
342 if (GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK & locationExtended.flags) {
343 out.flags |= GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT;
344 out.navSolutionMask = locationExtended.navSolutionMask;
345 }
346 if (GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK & locationExtended.flags) {
347 out.flags |= GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK;
348 out.posTechMask = locationExtended.tech_mask;
349 }
350 if (GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA & locationExtended.flags) {
351 out.flags |= GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA;
352 if (locationExtended.bodyFrameData.bodyFrameDatamask &
353 LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT) {
354 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT;
355 }
356 if (locationExtended.bodyFrameData.bodyFrameDatamask &
357 LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT) {
358 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT;
359 }
360 if (locationExtended.bodyFrameData.bodyFrameDatamask &
361 LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT) {
362 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT;
363 }
364 if (locationExtended.bodyFrameData.bodyFrameDatamask & LOCATION_NAV_DATA_HAS_YAW_RATE_BIT) {
365 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_BIT;
366 }
367 if (locationExtended.bodyFrameData.bodyFrameDatamask & LOCATION_NAV_DATA_HAS_PITCH_BIT) {
368 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_BIT;
369 }
370 out.bodyFrameData.longAccel = locationExtended.bodyFrameData.longAccel;
371 out.bodyFrameData.latAccel = locationExtended.bodyFrameData.latAccel;
372 out.bodyFrameData.vertAccel = locationExtended.bodyFrameData.vertAccel;
373 out.bodyFrameData.yawRate = locationExtended.bodyFrameData.yawRate;
374 out.bodyFrameData.pitch = locationExtended.bodyFrameData.pitch;
375 }
376 }
377
378 inline uint32_t
convertGpsLock(const GnssConfigGpsLock gpsLock)379 GnssAdapter::convertGpsLock(const GnssConfigGpsLock gpsLock)
380 {
381 switch (gpsLock) {
382 case GNSS_CONFIG_GPS_LOCK_MO:
383 return 1;
384 case GNSS_CONFIG_GPS_LOCK_NI:
385 return 2;
386 case GNSS_CONFIG_GPS_LOCK_MO_AND_NI:
387 return 3;
388 case GNSS_CONFIG_GPS_LOCK_NONE:
389 default:
390 return 0;
391 }
392 }
393
394 inline GnssConfigGpsLock
convertGpsLock(const uint32_t gpsLock)395 GnssAdapter::convertGpsLock(const uint32_t gpsLock)
396 {
397 switch (gpsLock) {
398 case 1:
399 return GNSS_CONFIG_GPS_LOCK_MO;
400 case 2:
401 return GNSS_CONFIG_GPS_LOCK_NI;
402 case 3:
403 return GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
404 case 0:
405 default:
406 return GNSS_CONFIG_GPS_LOCK_NONE;
407 }
408 }
409
410 inline uint32_t
convertSuplVersion(const GnssConfigSuplVersion suplVersion)411 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
412 {
413 switch (suplVersion) {
414 case GNSS_CONFIG_SUPL_VERSION_2_0_0:
415 return 0x00020000;
416 case GNSS_CONFIG_SUPL_VERSION_2_0_2:
417 return 0x00020002;
418 case GNSS_CONFIG_SUPL_VERSION_1_0_0:
419 default:
420 return 0x00010000;
421 }
422 }
423
424 inline GnssConfigSuplVersion
convertSuplVersion(const uint32_t suplVersion)425 GnssAdapter::convertSuplVersion(const uint32_t suplVersion)
426 {
427 switch (suplVersion) {
428 case 0x00020000:
429 return GNSS_CONFIG_SUPL_VERSION_2_0_0;
430 case 0x00020002:
431 return GNSS_CONFIG_SUPL_VERSION_2_0_2;
432 case 0x00010000:
433 default:
434 return GNSS_CONFIG_SUPL_VERSION_1_0_0;
435 }
436 }
437
438 inline uint32_t
convertLppProfile(const GnssConfigLppProfile lppProfile)439 GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile)
440 {
441 switch (lppProfile) {
442 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE:
443 return 1;
444 case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE:
445 return 2;
446 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE:
447 return 3;
448 case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE:
449 default:
450 return 0;
451 }
452 }
453
454 inline GnssConfigLppProfile
convertLppProfile(const uint32_t lppProfile)455 GnssAdapter::convertLppProfile(const uint32_t lppProfile)
456 {
457 switch (lppProfile) {
458 case 1:
459 return GNSS_CONFIG_LPP_PROFILE_USER_PLANE;
460 case 2:
461 return GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE;
462 case 3:
463 return GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE;
464 case 0:
465 default:
466 return GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE;
467 }
468 }
469
470 uint32_t
convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)471 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
472 {
473 uint32_t mask = 0;
474 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
475 mask |= (1<<0);
476 }
477 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
478 mask |= (1<<1);
479 }
480 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
481 mask |= (1<<2);
482 }
483 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeControlPlaneMask) {
484 mask |= (1<<3);
485 }
486 return mask;
487 }
488
489 GnssConfigLppeControlPlaneMask
convertLppeCp(const uint32_t lppeControlPlaneMask)490 GnssAdapter::convertLppeCp(const uint32_t lppeControlPlaneMask)
491 {
492 GnssConfigLppeControlPlaneMask mask = 0;
493 if ((1<<0) & lppeControlPlaneMask) {
494 mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT;
495 }
496 if ((1<<1) & lppeControlPlaneMask) {
497 mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT;
498 }
499 if ((1<<2) & lppeControlPlaneMask) {
500 mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT;
501 }
502 if ((1<<3) & lppeControlPlaneMask) {
503 mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT;
504 }
505 return mask;
506 }
507
508
509 uint32_t
convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)510 GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
511 {
512 uint32_t mask = 0;
513 if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
514 mask |= (1<<0);
515 }
516 if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
517 mask |= (1<<1);
518 }
519 if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
520 mask |= (1<<2);
521 }
522 if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUserPlaneMask) {
523 mask |= (1<<3);
524 }
525 return mask;
526 }
527
528 GnssConfigLppeUserPlaneMask
convertLppeUp(const uint32_t lppeUserPlaneMask)529 GnssAdapter::convertLppeUp(const uint32_t lppeUserPlaneMask)
530 {
531 GnssConfigLppeUserPlaneMask mask = 0;
532 if ((1<<0) & lppeUserPlaneMask) {
533 mask |= GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT;
534 }
535 if ((1<<1) & lppeUserPlaneMask) {
536 mask |= GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT;
537 }
538 if ((1<<2) & lppeUserPlaneMask) {
539 mask |= GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT;
540 }
541 if ((1<<3) & lppeUserPlaneMask) {
542 mask |= GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT;
543 }
544 return mask;
545 }
546
547 uint32_t
convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)548 GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
549 {
550 uint32_t mask = 0;
551 if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
552 mask |= (1<<0);
553 }
554 if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
555 mask |= (1<<1);
556 }
557 if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
558 mask |= (1<<2);
559 }
560 if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
561 mask |= (1<<3);
562 }
563 return mask;
564 }
565
566 uint32_t
convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)567 GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
568 {
569 switch (emergencyPdnForEmergencySupl) {
570 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
571 return 1;
572 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
573 default:
574 return 0;
575 }
576 }
577
578 uint32_t
convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)579 GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
580 {
581 switch (suplEmergencyServices) {
582 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
583 return 1;
584 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
585 default:
586 return 0;
587 }
588 }
589
590 uint32_t
convertSuplMode(const GnssConfigSuplModeMask suplModeMask)591 GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
592 {
593 uint32_t mask = 0;
594 if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
595 mask |= (1<<0);
596 }
597 if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
598 mask |= (1<<1);
599 }
600 return mask;
601 }
602
603 bool
resolveInAddress(const char * hostAddress,struct in_addr * inAddress)604 GnssAdapter::resolveInAddress(const char* hostAddress, struct in_addr* inAddress)
605 {
606 bool ret = true;
607
608 struct hostent* hp;
609 hp = gethostbyname(hostAddress);
610 if (hp != NULL) { /* DNS OK */
611 memcpy(inAddress, hp->h_addr_list[0], hp->h_length);
612 } else {
613 /* Try IP representation */
614 if (inet_aton(hostAddress, inAddress) == 0) {
615 /* IP not valid */
616 LOC_LOGE("%s]: DNS query on '%s' failed", __func__, hostAddress);
617 ret = false;
618 }
619 }
620
621 return ret;
622 }
623
624 void
readConfigCommand()625 GnssAdapter::readConfigCommand()
626 {
627 LOC_LOGD("%s]: ", __func__);
628
629 struct MsgReadConfig : public LocMsg {
630 GnssAdapter* mAdapter;
631 ContextBase& mContext;
632 inline MsgReadConfig(GnssAdapter* adapter,
633 ContextBase& context) :
634 LocMsg(),
635 mAdapter(adapter),
636 mContext(context) {}
637 inline virtual void proc() const {
638 // reads config into mContext->mGps_conf
639 mContext.readConfig();
640 mContext.requestUlp((LocAdapterBase*)mAdapter, mContext.getCarrierCapabilities());
641 }
642 };
643
644 if (mContext != NULL) {
645 sendMsg(new MsgReadConfig(this, *mContext));
646 }
647 }
648
649 LocationError
setSuplHostServer(const char * server,int port)650 GnssAdapter::setSuplHostServer(const char* server, int port)
651 {
652 LocationError locErr = LOCATION_ERROR_SUCCESS;
653 if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
654 char serverUrl[MAX_URL_LEN] = {};
655 int32_t length = -1;
656 const char noHost[] = "NONE";
657
658 locErr = LOCATION_ERROR_INVALID_PARAMETER;
659
660 if ((NULL == server) || (server[0] == 0) ||
661 (strncasecmp(noHost, server, sizeof(noHost)) == 0)) {
662 serverUrl[0] = '\0';
663 length = 0;
664 } else if (port > 0) {
665 length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", server, port);
666 }
667
668 if (length >= 0 && strncasecmp(getServerUrl().c_str(),
669 serverUrl, sizeof(serverUrl)) != 0) {
670 setServerUrl(serverUrl);
671 locErr = mLocApi->setServer(serverUrl, length);
672 if (locErr != LOCATION_ERROR_SUCCESS) {
673 LOC_LOGE("%s]:Error while setting SUPL_HOST server:%s",
674 __func__, serverUrl);
675 }
676 }
677 }
678 return locErr;
679 }
680
681 void
setConfigCommand()682 GnssAdapter::setConfigCommand()
683 {
684 LOC_LOGD("%s]: ", __func__);
685
686 struct MsgSetConfig : public LocMsg {
687 GnssAdapter& mAdapter;
688 LocApiBase& mApi;
689 inline MsgSetConfig(GnssAdapter& adapter,
690 LocApiBase& api) :
691 LocMsg(),
692 mAdapter(adapter),
693 mApi(api) {}
694 inline virtual void proc() const {
695 if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
696 mApi.setSUPLVersion(mAdapter.convertSuplVersion(ContextBase::mGps_conf.SUPL_VER));
697 mApi.setLPPConfig(mAdapter.convertLppProfile(ContextBase::mGps_conf.LPP_PROFILE));
698 mApi.setAGLONASSProtocol(ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT);
699 }
700 mAdapter.setSuplHostServer(ContextBase::mGps_conf.SUPL_HOST,
701 ContextBase::mGps_conf.SUPL_PORT);
702 mApi.setSensorControlConfig(ContextBase::mSap_conf.SENSOR_USAGE,
703 ContextBase::mSap_conf.SENSOR_PROVIDER);
704
705 /* Mark these LPPe functions, they are MBN configured.
706 mApi.setLPPeProtocolCp(
707 mAdapter.convertLppeCp(ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY));
708 mApi.setLPPeProtocolUp(
709 mAdapter.convertLppeUp(ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY));
710 */
711
712 // set nmea mask type
713 uint32_t mask = 0;
714 if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
715 mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
716 }
717 if (mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
718 mask |= LOC_NMEA_MASK_DEBUG_V02;
719 }
720 if (mask != 0) {
721 mApi.setNMEATypes(mask);
722 }
723 mAdapter.mNmeaMask= mask;
724
725 mApi.setXtraVersionCheck(ContextBase::mGps_conf.XTRA_VERSION_CHECK);
726 if (ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID ||
727 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
728 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
729 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
730 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
731 mApi.setSensorProperties(
732 ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID,
733 ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK,
734 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
735 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
736 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
737 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
738 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
739 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
740 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
741 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
742 }
743 mApi.setSensorPerfControlConfig(
744 ContextBase::mSap_conf.SENSOR_CONTROL_MODE,
745 ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
746 ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC,
747 ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH,
748 ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC,
749 ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
750 ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
751 ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
752 ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
753 ContextBase::mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK);
754 }
755 };
756
757 sendMsg(new MsgSetConfig(*this, *mLocApi));
758 }
759
760 uint32_t*
gnssUpdateConfigCommand(GnssConfig config)761 GnssAdapter::gnssUpdateConfigCommand(GnssConfig config)
762 {
763 // count the number of bits set
764 GnssConfigFlagsMask flagsCopy = config.flags;
765 size_t count = 0;
766 while (flagsCopy > 0) {
767 if (flagsCopy & 1) {
768 count++;
769 }
770 flagsCopy >>= 1;
771 }
772 std::string idsString = "[";
773 uint32_t* ids = NULL;
774 if (count > 0) {
775 ids = new uint32_t[count];
776 if (ids == nullptr) {
777 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
778 return nullptr;
779 }
780 for (size_t i=0; i < count; ++i) {
781 ids[i] = generateSessionId();
782 IF_LOC_LOGD {
783 idsString += std::to_string(ids[i]) + " ";
784 }
785 }
786 }
787 idsString += "]";
788
789 LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
790
791 struct MsgGnssUpdateConfig : public LocMsg {
792 GnssAdapter& mAdapter;
793 LocApiBase& mApi;
794 GnssConfig mConfig;
795 uint32_t* mIds;
796 size_t mCount;
797 inline MsgGnssUpdateConfig(GnssAdapter& adapter,
798 LocApiBase& api,
799 GnssConfig config,
800 uint32_t* ids,
801 size_t count) :
802 LocMsg(),
803 mAdapter(adapter),
804 mApi(api),
805 mConfig(config),
806 mIds(ids),
807 mCount(count) {}
808 inline virtual ~MsgGnssUpdateConfig()
809 {
810 delete[] mIds;
811 }
812 inline virtual void proc() const {
813 LocationError* errs = new LocationError[mCount];
814 LocationError err = LOCATION_ERROR_SUCCESS;
815 uint32_t index = 0;
816
817 if (errs == nullptr) {
818 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
819 return;
820 }
821
822 if (mConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
823 uint32_t newGpsLock = mAdapter.convertGpsLock(mConfig.gpsLock);
824 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
825 if (0 == ContextBase::mGps_conf.GPS_LOCK) {
826 // we should minimally lock MO
827 ContextBase::mGps_conf.GPS_LOCK = 1;
828 }
829 if (0 == mAdapter.getPowerVoteId()) {
830 err = mApi.setGpsLock(mConfig.gpsLock);
831 }
832 if (index < mCount) {
833 errs[index++] = err;
834 }
835 }
836 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
837 uint32_t newSuplVersion = mAdapter.convertSuplVersion(mConfig.suplVersion);
838 if (newSuplVersion != ContextBase::mGps_conf.SUPL_VER &&
839 ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
840 ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
841 err = mApi.setSUPLVersion(mConfig.suplVersion);
842 } else {
843 err = LOCATION_ERROR_SUCCESS;
844 }
845 if (index < mCount) {
846 errs[index++] = err;
847 }
848 }
849 if (mConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
850 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
851 err = mAdapter.setSuplHostServer(mConfig.assistanceServer.hostName,
852 mConfig.assistanceServer.port);
853 } else if (GNSS_ASSISTANCE_TYPE_C2K == mConfig.assistanceServer.type) {
854 if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
855 struct in_addr addr;
856 if (!mAdapter.resolveInAddress(mConfig.assistanceServer.hostName,
857 &addr)) {
858 LOC_LOGE("%s]: hostName %s cannot be resolved",
859 __func__, mConfig.assistanceServer.hostName);
860 err = LOCATION_ERROR_INVALID_PARAMETER;
861 } else {
862 unsigned int ip = htonl(addr.s_addr);
863 err = mApi.setServer(ip, mConfig.assistanceServer.port,
864 LOC_AGPS_CDMA_PDE_SERVER);
865 }
866 } else {
867 err = LOCATION_ERROR_SUCCESS;
868 }
869 } else {
870 LOC_LOGE("%s]: Not a valid gnss assistance type %u",
871 __func__, mConfig.assistanceServer.type);
872 err = LOCATION_ERROR_INVALID_PARAMETER;
873 }
874 if (index < mCount) {
875 errs[index++] = err;
876 }
877 }
878 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
879 uint32_t newLppProfile = mAdapter.convertLppProfile(mConfig.lppProfile);
880 if (newLppProfile != ContextBase::mGps_conf.LPP_PROFILE &&
881 ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
882 ContextBase::mGps_conf.LPP_PROFILE = newLppProfile;
883 err = mApi.setLPPConfig(mConfig.lppProfile);
884 } else {
885 err = LOCATION_ERROR_SUCCESS;
886 }
887 if (index < mCount) {
888 errs[index++] = err;
889 }
890 }
891 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
892 uint32_t newLppeControlPlaneMask =
893 mAdapter.convertLppeCp(mConfig.lppeControlPlaneMask);
894 if (newLppeControlPlaneMask != ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY) {
895 ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
896 err = mApi.setLPPeProtocolCp(mConfig.lppeControlPlaneMask);
897 } else {
898 err = LOCATION_ERROR_SUCCESS;
899 }
900 if (index < mCount) {
901 errs[index++] = err;
902 }
903 }
904 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
905 uint32_t newLppeUserPlaneMask =
906 mAdapter.convertLppeUp(mConfig.lppeUserPlaneMask);
907 if (newLppeUserPlaneMask != ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY) {
908 ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
909 err = mApi.setLPPeProtocolUp(mConfig.lppeUserPlaneMask);
910 } else {
911 err = LOCATION_ERROR_SUCCESS;
912 }
913 if (index < mCount) {
914 errs[index++] = err;
915 }
916 }
917 if (mConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
918 uint32_t newAGloProtMask =
919 mAdapter.convertAGloProt(mConfig.aGlonassPositionProtocolMask);
920 if (newAGloProtMask != ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT &&
921 ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
922 ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
923 err = mApi.setAGLONASSProtocol(mConfig.aGlonassPositionProtocolMask);
924 } else {
925 err = LOCATION_ERROR_SUCCESS;
926 }
927 if (index < mCount) {
928 errs[index++] = err;
929 }
930 }
931 if (mConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
932 uint32_t newEP4ES = mAdapter.convertEP4ES(mConfig.emergencyPdnForEmergencySupl);
933 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
934 ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
935 }
936 err = LOCATION_ERROR_SUCCESS;
937 if (index < mCount) {
938 errs[index++] = err;
939 }
940 }
941 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
942 uint32_t newSuplEs = mAdapter.convertSuplEs(mConfig.suplEmergencyServices);
943 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
944 ContextBase::mGps_conf.SUPL_ES = newSuplEs;
945 }
946 err = LOCATION_ERROR_SUCCESS;
947 if (index < mCount) {
948 errs[index++] = err;
949 }
950 }
951 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
952 uint32_t newSuplMode = mAdapter.convertSuplMode(mConfig.suplModeMask);
953 if (newSuplMode != ContextBase::mGps_conf.SUPL_MODE) {
954 ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
955 mAdapter.getUlpProxy()->setCapabilities(
956 ContextBase::getCarrierCapabilities());
957 mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
958 }
959 err = LOCATION_ERROR_SUCCESS;
960 if (index < mCount) {
961 errs[index++] = err;
962 }
963 }
964 if (mConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
965 // Check if feature is supported
966 if (!mApi.isFeatureSupported(
967 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
968 LOC_LOGe("Feature constellation enablement not supported.");
969 err = LOCATION_ERROR_NOT_SUPPORTED;
970 } else {
971 // Send the SV ID Config to Modem
972 err = mAdapter.gnssSvIdConfigUpdate(mConfig.blacklistedSvIds);
973 if (LOCATION_ERROR_SUCCESS != err) {
974 LOC_LOGe("Failed to send config to modem, err %d", err);
975 }
976 }
977 if (index < mCount) {
978 errs[index++] = err;
979 }
980 }
981
982 mAdapter.reportResponse(index, errs, mIds);
983 delete[] errs;
984 }
985 };
986
987 if (NULL != ids) {
988 sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
989 } else {
990 LOC_LOGE("%s]: No GNSS config items to update", __func__);
991 }
992
993 return ids;
994 }
995
996 LocationError
gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource> & blacklistedSvIds)997 GnssAdapter::gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource>& blacklistedSvIds)
998 {
999 // Clear the existing config
1000 memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1001
1002 // Convert the sv id lists to masks
1003 bool convertSuccess = convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1004
1005 // Now send to Modem if conversion successful
1006 if (convertSuccess) {
1007 return gnssSvIdConfigUpdate();
1008 } else {
1009 LOC_LOGe("convertToGnssSvIdConfig failed");
1010 return LOCATION_ERROR_INVALID_PARAMETER;
1011 }
1012 }
1013
1014 LocationError
gnssSvIdConfigUpdate()1015 GnssAdapter::gnssSvIdConfigUpdate()
1016 {
1017 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1018 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
1019 mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1020 mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask);
1021
1022 // Now set required blacklisted SVs
1023 return mLocApi->setBlacklistSv(mGnssSvIdConfig);
1024 }
1025
1026 uint32_t*
gnssGetConfigCommand(GnssConfigFlagsMask configMask)1027 GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) {
1028
1029 // count the number of bits set
1030 GnssConfigFlagsMask flagsCopy = configMask;
1031 size_t count = 0;
1032 while (flagsCopy > 0) {
1033 if (flagsCopy & 1) {
1034 count++;
1035 }
1036 flagsCopy >>= 1;
1037 }
1038 std::string idsString = "[";
1039 uint32_t* ids = NULL;
1040 if (count > 0) {
1041 ids = new uint32_t[count];
1042 if (nullptr == ids) {
1043 LOC_LOGe("new allocation failed, fatal error.");
1044 return nullptr;
1045 }
1046 for (size_t i=0; i < count; ++i) {
1047 ids[i] = generateSessionId();
1048 IF_LOC_LOGD {
1049 idsString += std::to_string(ids[i]) + " ";
1050 }
1051 }
1052 }
1053 idsString += "]";
1054
1055 LOC_LOGd("ids %s flags 0x%X", idsString.c_str(), configMask);
1056
1057 struct MsgGnssGetConfig : public LocMsg {
1058 GnssAdapter& mAdapter;
1059 LocApiBase& mApi;
1060 GnssConfigFlagsMask mConfigMask;
1061 uint32_t* mIds;
1062 size_t mCount;
1063 inline MsgGnssGetConfig(GnssAdapter& adapter,
1064 LocApiBase& api,
1065 GnssConfigFlagsMask configMask,
1066 uint32_t* ids,
1067 size_t count) :
1068 LocMsg(),
1069 mAdapter(adapter),
1070 mApi(api),
1071 mConfigMask(configMask),
1072 mIds(ids),
1073 mCount(count) {}
1074 inline virtual ~MsgGnssGetConfig()
1075 {
1076 delete[] mIds;
1077 }
1078 inline virtual void proc() const {
1079
1080 LocationError* errs = new LocationError[mCount];
1081 LocationError err = LOCATION_ERROR_SUCCESS;
1082 uint32_t index = 0;
1083
1084 if (nullptr == errs) {
1085 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1086 return;
1087 }
1088
1089 if (mConfigMask & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1090 if (index < mCount) {
1091 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1092 }
1093 }
1094 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1095 if (index < mCount) {
1096 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1097 }
1098 }
1099 if (mConfigMask & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1100 if (index < mCount) {
1101 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1102 }
1103 }
1104 if (mConfigMask & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1105 if (index < mCount) {
1106 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1107 }
1108 }
1109 if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1110 if (index < mCount) {
1111 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1112 }
1113 }
1114 if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1115 if (index < mCount) {
1116 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1117 }
1118 }
1119 if (mConfigMask & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1120 if (index < mCount) {
1121 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1122 }
1123 }
1124 if (mConfigMask & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1125 if (index < mCount) {
1126 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1127 }
1128 }
1129 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1130 if (index < mCount) {
1131 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1132 }
1133 }
1134 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1135 err = LOCATION_ERROR_NOT_SUPPORTED;
1136 if (index < mCount) {
1137 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1138 }
1139 }
1140 if (mConfigMask & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
1141 // Check if feature is supported
1142 if (!mApi.isFeatureSupported(
1143 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1144 LOC_LOGe("Feature not supported.");
1145 err = LOCATION_ERROR_NOT_SUPPORTED;
1146 } else {
1147 // Send request to Modem to fetch the config
1148 err = mApi.getBlacklistSv();
1149 if (LOCATION_ERROR_SUCCESS != err) {
1150 LOC_LOGe("getConfig request to modem failed, err %d", err);
1151 }
1152 }
1153 if (index < mCount) {
1154 errs[index++] = err;
1155 }
1156 }
1157
1158 mAdapter.reportResponse(index, errs, mIds);
1159 delete[] errs;
1160 }
1161 };
1162
1163 if (NULL != ids) {
1164 sendMsg(new MsgGnssGetConfig(*this, *mLocApi, configMask, ids, count));
1165 } else {
1166 LOC_LOGe("No GNSS config items to Get");
1167 }
1168
1169 return ids;
1170 }
1171
1172 bool
convertToGnssSvIdConfig(const std::vector<GnssSvIdSource> & blacklistedSvIds,GnssSvIdConfig & config)1173 GnssAdapter::convertToGnssSvIdConfig(
1174 const std::vector<GnssSvIdSource>& blacklistedSvIds, GnssSvIdConfig& config)
1175 {
1176 bool retVal = true;
1177 config.size = sizeof(GnssSvIdConfig);
1178
1179 // Empty vector => Clear any previous blacklisted SVs
1180 if (0 == blacklistedSvIds.size()) {
1181 config.gloBlacklistSvMask = 0;
1182 config.bdsBlacklistSvMask = 0;
1183 config.qzssBlacklistSvMask = 0;
1184 config.galBlacklistSvMask = 0;
1185 } else {
1186 // Parse the vector and convert SV IDs to mask values
1187 for (GnssSvIdSource source : blacklistedSvIds) {
1188 uint64_t* svMaskPtr = NULL;
1189 GnssSvId initialSvId = 0;
1190 GnssSvId lastSvId = 0;
1191 switch(source.constellation) {
1192 case GNSS_SV_TYPE_GLONASS:
1193 svMaskPtr = &config.gloBlacklistSvMask;
1194 initialSvId = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID;
1195 lastSvId = GNSS_SV_CONFIG_GLO_LAST_SV_ID;
1196 break;
1197 case GNSS_SV_TYPE_BEIDOU:
1198 svMaskPtr = &config.bdsBlacklistSvMask;
1199 initialSvId = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID;
1200 lastSvId = GNSS_SV_CONFIG_BDS_LAST_SV_ID;
1201 break;
1202 case GNSS_SV_TYPE_QZSS:
1203 svMaskPtr = &config.qzssBlacklistSvMask;
1204 initialSvId = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID;
1205 lastSvId = GNSS_SV_CONFIG_QZSS_LAST_SV_ID;
1206 break;
1207 case GNSS_SV_TYPE_GALILEO:
1208 svMaskPtr = &config.galBlacklistSvMask;
1209 initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID;
1210 lastSvId = GNSS_SV_CONFIG_GAL_LAST_SV_ID;
1211 break;
1212 default:
1213 break;
1214 }
1215
1216 if (NULL == svMaskPtr) {
1217 LOC_LOGe("Invalid constellation %d", source.constellation);
1218 } else {
1219 // SV ID 0 = All SV IDs
1220 if (0 == source.svId) {
1221 *svMaskPtr = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1222 } else if (source.svId < initialSvId || source.svId > lastSvId) {
1223 LOC_LOGe("Invalid sv id %d for sv type %d allowed range [%d, %d]",
1224 source.svId, source.constellation, initialSvId, lastSvId);
1225 } else {
1226 *svMaskPtr |= ((uint64_t)1 << (source.svId - initialSvId));
1227 }
1228 }
1229 }
1230 }
1231
1232 return retVal;
1233 }
1234
convertFromGnssSvIdConfig(const GnssSvIdConfig & svConfig,GnssConfig & config)1235 void GnssAdapter::convertFromGnssSvIdConfig(
1236 const GnssSvIdConfig& svConfig, GnssConfig& config)
1237 {
1238 // Convert blacklisted SV mask values to vectors
1239 if (svConfig.bdsBlacklistSvMask) {
1240 convertGnssSvIdMaskToList(
1241 svConfig.bdsBlacklistSvMask, config.blacklistedSvIds,
1242 GNSS_SV_CONFIG_BDS_INITIAL_SV_ID, GNSS_SV_TYPE_BEIDOU);
1243 config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1244 }
1245 if (svConfig.galBlacklistSvMask) {
1246 convertGnssSvIdMaskToList(
1247 svConfig.galBlacklistSvMask, config.blacklistedSvIds,
1248 GNSS_SV_CONFIG_GAL_INITIAL_SV_ID, GNSS_SV_TYPE_GALILEO);
1249 config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1250 }
1251 if (svConfig.gloBlacklistSvMask) {
1252 convertGnssSvIdMaskToList(
1253 svConfig.gloBlacklistSvMask, config.blacklistedSvIds,
1254 GNSS_SV_CONFIG_GLO_INITIAL_SV_ID, GNSS_SV_TYPE_GLONASS);
1255 config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1256 }
1257 if (svConfig.qzssBlacklistSvMask) {
1258 convertGnssSvIdMaskToList(
1259 svConfig.qzssBlacklistSvMask, config.blacklistedSvIds,
1260 GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID, GNSS_SV_TYPE_QZSS);
1261 config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1262 }
1263 }
1264
convertGnssSvIdMaskToList(uint64_t svIdMask,std::vector<GnssSvIdSource> & svIds,GnssSvId initialSvId,GnssSvType svType)1265 void GnssAdapter::convertGnssSvIdMaskToList(
1266 uint64_t svIdMask, std::vector<GnssSvIdSource>& svIds,
1267 GnssSvId initialSvId, GnssSvType svType)
1268 {
1269 GnssSvIdSource source = {};
1270 source.size = sizeof(GnssSvIdSource);
1271 source.constellation = svType;
1272
1273 // SV ID 0 => All SV IDs in mask
1274 if (GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK == svIdMask) {
1275 source.svId = 0;
1276 svIds.push_back(source);
1277 return;
1278 }
1279
1280 // Convert each bit in svIdMask to vector entry
1281 uint32_t bitNumber = 0;
1282 while (svIdMask > 0) {
1283 if (svIdMask & 0x1) {
1284 source.svId = bitNumber + initialSvId;
1285 svIds.push_back(source);
1286 }
1287 bitNumber++;
1288 svIdMask >>= 1;
1289 }
1290 }
1291
reportGnssSvIdConfigEvent(const GnssSvIdConfig & config)1292 void GnssAdapter::reportGnssSvIdConfigEvent(const GnssSvIdConfig& config)
1293 {
1294 struct MsgReportGnssSvIdConfig : public LocMsg {
1295 GnssAdapter& mAdapter;
1296 const GnssSvIdConfig mConfig;
1297 inline MsgReportGnssSvIdConfig(GnssAdapter& adapter,
1298 const GnssSvIdConfig& config) :
1299 LocMsg(),
1300 mAdapter(adapter),
1301 mConfig(config) {}
1302 inline virtual void proc() const {
1303 mAdapter.reportGnssSvIdConfig(mConfig);
1304 }
1305 };
1306
1307 sendMsg(new MsgReportGnssSvIdConfig(*this, config));
1308 }
1309
reportGnssSvIdConfig(const GnssSvIdConfig & svIdConfig)1310 void GnssAdapter::reportGnssSvIdConfig(const GnssSvIdConfig& svIdConfig)
1311 {
1312 GnssConfig config = {};
1313 config.size = sizeof(GnssConfig);
1314
1315 // Invoke control clients config callback
1316 if (nullptr != mControlCallbacks.gnssConfigCb &&
1317 svIdConfig.size == sizeof(GnssSvIdConfig)) {
1318 convertFromGnssSvIdConfig(svIdConfig, config);
1319 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1320 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
1321 svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask,
1322 svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask);
1323 mControlCallbacks.gnssConfigCb(config);
1324 } else {
1325 LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
1326 }
1327 }
1328
1329 void
gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)1330 GnssAdapter::gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)
1331 {
1332 struct MsgGnssUpdateSvTypeConfig : public LocMsg {
1333 GnssAdapter* mAdapter;
1334 LocApiBase* mApi;
1335 GnssSvTypeConfig mConfig;
1336 inline MsgGnssUpdateSvTypeConfig(
1337 GnssAdapter* adapter,
1338 LocApiBase* api,
1339 GnssSvTypeConfig& config) :
1340 LocMsg(),
1341 mAdapter(adapter),
1342 mApi(api),
1343 mConfig(config) {}
1344 inline virtual void proc() const {
1345 // Check if feature is supported
1346 if (!mApi->isFeatureSupported(
1347 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1348 LOC_LOGe("Feature not supported.");
1349 } else {
1350 // Send update request to modem
1351 LocationError err = mAdapter->gnssSvTypeConfigUpdate(mConfig);
1352 if (err != LOCATION_ERROR_SUCCESS) {
1353 LOC_LOGe("Set constellation request failed, err %d", err);
1354 }
1355 }
1356 }
1357 };
1358
1359 sendMsg(new MsgGnssUpdateSvTypeConfig(this, mLocApi, config));
1360 }
1361
1362 LocationError
gnssSvTypeConfigUpdate(const GnssSvTypeConfig & config)1363 GnssAdapter::gnssSvTypeConfigUpdate(const GnssSvTypeConfig& config)
1364 {
1365 gnssSetSvTypeConfig(config);
1366 return gnssSvTypeConfigUpdate();
1367 }
1368
1369 LocationError
gnssSvTypeConfigUpdate()1370 GnssAdapter::gnssSvTypeConfigUpdate()
1371 {
1372 LocationError err = LOCATION_ERROR_GENERAL_FAILURE;
1373 LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
1374 mGnssSvTypeConfig.blacklistedSvTypesMask, mGnssSvTypeConfig.enabledSvTypesMask);
1375
1376 if (mGnssSvTypeConfig.size == sizeof(mGnssSvTypeConfig)) {
1377 GnssSvIdConfig blacklistConfig = {};
1378 // Revert to previously blacklisted SVs for each enabled constellation
1379 blacklistConfig = mGnssSvIdConfig;
1380 // Blacklist all SVs for each disabled constellation
1381 if (mGnssSvTypeConfig.blacklistedSvTypesMask) {
1382 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GLO_BIT) {
1383 blacklistConfig.gloBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1384 }
1385 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_BDS_BIT) {
1386 blacklistConfig.bdsBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1387 }
1388 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_QZSS_BIT) {
1389 blacklistConfig.qzssBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1390 }
1391 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GAL_BIT) {
1392 blacklistConfig.galBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1393 }
1394 }
1395
1396 // Send blacklist info
1397 err = mLocApi->setBlacklistSv(blacklistConfig);
1398 if (LOCATION_ERROR_SUCCESS != err) {
1399 LOC_LOGE("Failed to send Set Blacklist");
1400 }
1401 // Send only enabled constellation config
1402 if (mGnssSvTypeConfig.enabledSvTypesMask) {
1403 GnssSvTypeConfig svTypeConfig = {sizeof(GnssSvTypeConfig), 0, 0};
1404 svTypeConfig.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask;
1405 err = mLocApi->setConstellationControl(svTypeConfig);
1406 if (LOCATION_ERROR_SUCCESS != err) {
1407 LOC_LOGE("Failed to send Set Constellation");
1408 }
1409 }
1410 } else {
1411 LOC_LOGE("Invalid GnssSvTypeConfig size");
1412 err = LOCATION_ERROR_SUCCESS;
1413 }
1414
1415 return err;
1416 }
1417
1418 void
gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)1419 GnssAdapter::gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)
1420 {
1421 struct MsgGnssGetSvTypeConfig : public LocMsg {
1422 GnssAdapter* mAdapter;
1423 LocApiBase* mApi;
1424 GnssSvTypeConfigCallback mCallback;
1425 inline MsgGnssGetSvTypeConfig(
1426 GnssAdapter* adapter,
1427 LocApiBase* api,
1428 GnssSvTypeConfigCallback callback) :
1429 LocMsg(),
1430 mAdapter(adapter),
1431 mApi(api),
1432 mCallback(callback) {}
1433 inline virtual void proc() const {
1434 if (!mApi->isFeatureSupported(
1435 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1436 LOC_LOGe("Feature not supported.");
1437 } else {
1438 // Save the callback
1439 mAdapter->gnssSetSvTypeConfigCallback(mCallback);
1440 // Send GET request to modem
1441 LocationError err = mApi->getConstellationControl();
1442 if (err != LOCATION_ERROR_SUCCESS) {
1443 LOC_LOGe("Get constellation request failed, err %d", err);
1444 }
1445 }
1446 }
1447 };
1448
1449 sendMsg(new MsgGnssGetSvTypeConfig(this, mLocApi, callback));
1450 }
1451
1452 void
gnssResetSvTypeConfigCommand()1453 GnssAdapter::gnssResetSvTypeConfigCommand()
1454 {
1455 struct MsgGnssResetSvTypeConfig : public LocMsg {
1456 GnssAdapter* mAdapter;
1457 LocApiBase* mApi;
1458 inline MsgGnssResetSvTypeConfig(
1459 GnssAdapter* adapter,
1460 LocApiBase* api) :
1461 LocMsg(),
1462 mAdapter(adapter),
1463 mApi(api) {}
1464 inline virtual void proc() const {
1465 if (!mApi->isFeatureSupported(
1466 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1467 LOC_LOGe("Feature not supported.");
1468 } else {
1469 // Reset constellation config
1470 mAdapter->gnssSetSvTypeConfig({sizeof(GnssSvTypeConfig), 0, 0});
1471 // Re-enforce SV blacklist config
1472 LocationError err = mAdapter->gnssSvIdConfigUpdate();
1473 if (err != LOCATION_ERROR_SUCCESS) {
1474 LOC_LOGe("SV Config request failed, err %d", err);
1475 }
1476 // Send reset request to modem
1477 err = mApi->resetConstellationControl();
1478 if (err != LOCATION_ERROR_SUCCESS) {
1479 LOC_LOGe("Reset constellation request failed, err %d", err);
1480 }
1481 }
1482 }
1483 };
1484
1485 sendMsg(new MsgGnssResetSvTypeConfig(this, mLocApi));
1486 }
1487
reportGnssSvTypeConfigEvent(const GnssSvTypeConfig & config)1488 void GnssAdapter::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config)
1489 {
1490 struct MsgReportGnssSvTypeConfig : public LocMsg {
1491 GnssAdapter& mAdapter;
1492 const GnssSvTypeConfig mConfig;
1493 inline MsgReportGnssSvTypeConfig(GnssAdapter& adapter,
1494 const GnssSvTypeConfig& config) :
1495 LocMsg(),
1496 mAdapter(adapter),
1497 mConfig(config) {}
1498 inline virtual void proc() const {
1499 mAdapter.reportGnssSvTypeConfig(mConfig);
1500 }
1501 };
1502
1503 sendMsg(new MsgReportGnssSvTypeConfig(*this, config));
1504 }
1505
reportGnssSvTypeConfig(const GnssSvTypeConfig & config)1506 void GnssAdapter::reportGnssSvTypeConfig(const GnssSvTypeConfig& config)
1507 {
1508 // Invoke Get SV Type Callback
1509 if (NULL != mGnssSvTypeConfigCb &&
1510 config.size == sizeof(GnssSvTypeConfig)) {
1511 LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
1512 config.blacklistedSvTypesMask, config.enabledSvTypesMask);
1513 mGnssSvTypeConfigCb(config);
1514 } else {
1515 LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
1516 }
1517 }
1518
1519 uint32_t
gnssDeleteAidingDataCommand(GnssAidingData & data)1520 GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
1521 {
1522 uint32_t sessionId = generateSessionId();
1523 LOC_LOGD("%s]: id %u", __func__, sessionId);
1524
1525 struct MsgDeleteAidingData : public LocMsg {
1526 GnssAdapter& mAdapter;
1527 LocApiBase& mApi;
1528 uint32_t mSessionId;
1529 GnssAidingData mData;
1530 inline MsgDeleteAidingData(GnssAdapter& adapter,
1531 LocApiBase& api,
1532 uint32_t sessionId,
1533 GnssAidingData& data) :
1534 LocMsg(),
1535 mAdapter(adapter),
1536 mApi(api),
1537 mSessionId(sessionId),
1538 mData(data) {}
1539 inline virtual void proc() const {
1540 LocationError err = LOCATION_ERROR_SUCCESS;
1541 err = mApi.deleteAidingData(mData);
1542 mAdapter.reportResponse(err, mSessionId);
1543 SystemStatus* s = mAdapter.getSystemStatus();
1544 if ((nullptr != s) && (mData.deleteAll)) {
1545 s->setDefaultGnssEngineStates();
1546 }
1547 }
1548 };
1549
1550 sendMsg(new MsgDeleteAidingData(*this, *mLocApi, sessionId, data));
1551 return sessionId;
1552 }
1553
1554 void
gnssUpdateXtraThrottleCommand(const bool enabled)1555 GnssAdapter::gnssUpdateXtraThrottleCommand(const bool enabled)
1556 {
1557 LOC_LOGD("%s] enabled:%d", __func__, enabled);
1558
1559 struct UpdateXtraThrottleMsg : public LocMsg {
1560 GnssAdapter& mAdapter;
1561 const bool mEnabled;
1562 inline UpdateXtraThrottleMsg(GnssAdapter& adapter, const bool enabled) :
1563 LocMsg(),
1564 mAdapter(adapter),
1565 mEnabled(enabled) {}
1566 inline virtual void proc() const {
1567 mAdapter.mXtraObserver.updateXtraThrottle(mEnabled);
1568 }
1569 };
1570
1571 sendMsg(new UpdateXtraThrottleMsg(*this, enabled));
1572 }
1573
1574 void
injectLocationCommand(double latitude,double longitude,float accuracy)1575 GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
1576 {
1577 LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
1578 __func__, latitude, longitude, accuracy);
1579
1580 struct MsgInjectLocation : public LocMsg {
1581 LocApiBase& mApi;
1582 ContextBase& mContext;
1583 double mLatitude;
1584 double mLongitude;
1585 float mAccuracy;
1586 inline MsgInjectLocation(LocApiBase& api,
1587 ContextBase& context,
1588 double latitude,
1589 double longitude,
1590 float accuracy) :
1591 LocMsg(),
1592 mApi(api),
1593 mContext(context),
1594 mLatitude(latitude),
1595 mLongitude(longitude),
1596 mAccuracy(accuracy) {}
1597 inline virtual void proc() const {
1598 if (!mContext.hasCPIExtendedCapabilities()) {
1599 mApi.injectPosition(mLatitude, mLongitude, mAccuracy);
1600 }
1601 }
1602 };
1603
1604 sendMsg(new MsgInjectLocation(*mLocApi, *mContext, latitude, longitude, accuracy));
1605 }
1606
1607 void
injectTimeCommand(int64_t time,int64_t timeReference,int32_t uncertainty)1608 GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
1609 {
1610 LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
1611 __func__, (long long)time, (long long)timeReference, uncertainty);
1612
1613 struct MsgInjectTime : public LocMsg {
1614 LocApiBase& mApi;
1615 ContextBase& mContext;
1616 int64_t mTime;
1617 int64_t mTimeReference;
1618 int32_t mUncertainty;
1619 inline MsgInjectTime(LocApiBase& api,
1620 ContextBase& context,
1621 int64_t time,
1622 int64_t timeReference,
1623 int32_t uncertainty) :
1624 LocMsg(),
1625 mApi(api),
1626 mContext(context),
1627 mTime(time),
1628 mTimeReference(timeReference),
1629 mUncertainty(uncertainty) {}
1630 inline virtual void proc() const {
1631 mApi.setTime(mTime, mTimeReference, mUncertainty);
1632 }
1633 };
1634
1635 sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
1636 }
1637
1638 void
setUlpProxyCommand(UlpProxyBase * ulp)1639 GnssAdapter::setUlpProxyCommand(UlpProxyBase* ulp)
1640 {
1641 LOC_LOGD("%s]: ", __func__);
1642
1643 struct MsgSetUlpProxy : public LocMsg {
1644 GnssAdapter& mAdapter;
1645 UlpProxyBase* mUlp;
1646 inline MsgSetUlpProxy(GnssAdapter& adapter,
1647 UlpProxyBase* ulp) :
1648 LocMsg(),
1649 mAdapter(adapter),
1650 mUlp(ulp) {}
1651 inline virtual void proc() const {
1652 mAdapter.setUlpProxy(mUlp);
1653 if (mUlp) {
1654 mUlp->setCapabilities(ContextBase::getCarrierCapabilities());
1655 }
1656 }
1657 };
1658
1659 sendMsg(new MsgSetUlpProxy(*this, ulp));
1660 }
1661
1662 void
setUlpProxy(UlpProxyBase * ulp)1663 GnssAdapter::setUlpProxy(UlpProxyBase* ulp)
1664 {
1665 if (ulp == mUlpProxy) {
1666 //This takes care of the case when double initalization happens
1667 //and we get the same object back for UlpProxyBase . Do nothing
1668 return;
1669 }
1670
1671 LOC_LOGV("%s]: %p", __func__, ulp);
1672 if (NULL == ulp) {
1673 LOC_LOGE("%s]: ulp pointer is NULL", __func__);
1674 ulp = new UlpProxyBase();
1675 }
1676
1677 if (LOC_POSITION_MODE_INVALID != mUlpProxy->mPosMode.mode) {
1678 // need to send this mode and start msg to ULP
1679 ulp->sendFixMode(mUlpProxy->mPosMode);
1680 }
1681
1682 if (mUlpProxy->mFixSet) {
1683 ulp->sendStartFix();
1684 }
1685
1686 delete mUlpProxy;
1687 mUlpProxy = ulp;
1688 }
1689
1690 void
addClientCommand(LocationAPI * client,const LocationCallbacks & callbacks)1691 GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
1692 {
1693 LOC_LOGD("%s]: client %p", __func__, client);
1694
1695 struct MsgAddClient : public LocMsg {
1696 GnssAdapter& mAdapter;
1697 LocationAPI* mClient;
1698 const LocationCallbacks mCallbacks;
1699 inline MsgAddClient(GnssAdapter& adapter,
1700 LocationAPI* client,
1701 const LocationCallbacks& callbacks) :
1702 LocMsg(),
1703 mAdapter(adapter),
1704 mClient(client),
1705 mCallbacks(callbacks) {}
1706 inline virtual void proc() const {
1707 mAdapter.saveClient(mClient, mCallbacks);
1708 }
1709 };
1710
1711 sendMsg(new MsgAddClient(*this, client, callbacks));
1712 }
1713
1714 void
removeClientCommand(LocationAPI * client)1715 GnssAdapter::removeClientCommand(LocationAPI* client)
1716 {
1717 LOC_LOGD("%s]: client %p", __func__, client);
1718
1719 struct MsgRemoveClient : public LocMsg {
1720 GnssAdapter& mAdapter;
1721 LocationAPI* mClient;
1722 inline MsgRemoveClient(GnssAdapter& adapter,
1723 LocationAPI* client) :
1724 LocMsg(),
1725 mAdapter(adapter),
1726 mClient(client) {}
1727 inline virtual void proc() const {
1728 mAdapter.stopClientSessions(mClient);
1729 mAdapter.eraseClient(mClient);
1730 }
1731 };
1732
1733 sendMsg(new MsgRemoveClient(*this, client));
1734 }
1735
1736 void
stopClientSessions(LocationAPI * client)1737 GnssAdapter::stopClientSessions(LocationAPI* client)
1738 {
1739 LOC_LOGD("%s]: client %p", __func__, client);
1740 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) {
1741 if (client == it->first.client) {
1742 LocationError err = stopTrackingMultiplex(it->first.client, it->first.id);
1743 if (LOCATION_ERROR_SUCCESS == err) {
1744 it = mTrackingSessions.erase(it);
1745 continue;
1746 }
1747 }
1748 ++it; // increment only when not erasing an iterator
1749 }
1750 }
1751
1752 void
updateClientsEventMask()1753 GnssAdapter::updateClientsEventMask()
1754 {
1755 LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
1756 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1757 if (it->second.trackingCb != nullptr || it->second.gnssLocationInfoCb != nullptr) {
1758 mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
1759 }
1760 if (it->second.gnssNiCb != nullptr) {
1761 mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
1762 }
1763 if (it->second.gnssSvCb != nullptr) {
1764 mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
1765 }
1766 if ((it->second.gnssNmeaCb != nullptr) && (mNmeaMask)) {
1767 mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
1768 }
1769 if (it->second.gnssMeasurementsCb != nullptr) {
1770 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
1771 }
1772 }
1773
1774 /*
1775 ** For Automotive use cases we need to enable MEASUREMENT and POLY
1776 ** when QDR is enabled
1777 */
1778 if (1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) {
1779 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
1780 mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT;
1781
1782 LOC_LOGD("%s]: Auto usecase, Enable MEAS/POLY - mask 0x%x", __func__, mask);
1783 }
1784
1785 if (mAgpsCbInfo.statusV4Cb != NULL) {
1786 mask |= LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST;
1787 }
1788
1789 // Add ODCPI handling
1790 if (nullptr != mOdcpiRequestCb) {
1791 mask |= LOC_API_ADAPTER_BIT_REQUEST_WIFI;
1792 }
1793
1794 updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
1795 }
1796
1797 void
handleEngineUpEvent()1798 GnssAdapter::handleEngineUpEvent()
1799 {
1800 struct MsgRestartSessions : public LocMsg {
1801 GnssAdapter& mAdapter;
1802 inline MsgRestartSessions(GnssAdapter& adapter) :
1803 LocMsg(),
1804 mAdapter(adapter) {}
1805 virtual void proc() const {
1806 mAdapter.restartSessions();
1807 mAdapter.gnssSvIdConfigUpdate();
1808 mAdapter.gnssSvTypeConfigUpdate();
1809 }
1810 };
1811
1812 setConfigCommand();
1813 sendMsg(new MsgRestartSessions(*this));
1814 }
1815
1816 void
restartSessions()1817 GnssAdapter::restartSessions()
1818 {
1819 LOC_LOGD("%s]: ", __func__);
1820
1821 // odcpi session is no longer active after restart
1822 mOdcpiRequestActive = false;
1823
1824 if (mTrackingSessions.empty()) {
1825 return;
1826 }
1827
1828 // get the LocationOptions that has the smallest interval, which should be the active one
1829 TrackingOptions smallestIntervalOptions = {}; // size is zero until set for the first time
1830 TrackingOptions highestPowerTrackingOptions = {};
1831 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
1832 // size of zero means we havent set it yet
1833 if (0 == smallestIntervalOptions.size ||
1834 it->second.minInterval < smallestIntervalOptions.minInterval) {
1835 smallestIntervalOptions = it->second;
1836 }
1837 GnssPowerMode powerMode = it->second.powerMode;
1838 // Size of zero means we havent set it yet
1839 if (0 == highestPowerTrackingOptions.size ||
1840 (GNSS_POWER_MODE_INVALID != powerMode &&
1841 powerMode < highestPowerTrackingOptions.powerMode)) {
1842 highestPowerTrackingOptions = it->second;
1843 }
1844 }
1845
1846 LocPosMode locPosMode = {};
1847 highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
1848 convertOptions(locPosMode, highestPowerTrackingOptions);
1849 mLocApi->startFix(locPosMode);
1850 }
1851
1852 void
requestCapabilitiesCommand(LocationAPI * client)1853 GnssAdapter::requestCapabilitiesCommand(LocationAPI* client)
1854 {
1855 LOC_LOGD("%s]: ", __func__);
1856
1857 struct MsgRequestCapabilities : public LocMsg {
1858 GnssAdapter& mAdapter;
1859 LocationAPI* mClient;
1860 inline MsgRequestCapabilities(GnssAdapter& adapter,
1861 LocationAPI* client) :
1862 LocMsg(),
1863 mAdapter(adapter),
1864 mClient(client) {}
1865 inline virtual void proc() const {
1866 LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient);
1867 if (callbacks.capabilitiesCb == nullptr) {
1868 LOC_LOGE("%s]: capabilitiesCb is NULL", __func__);
1869 return;
1870 }
1871
1872 LocationCapabilitiesMask mask = mAdapter.getCapabilities();
1873 callbacks.capabilitiesCb(mask);
1874 }
1875 };
1876
1877 sendMsg(new MsgRequestCapabilities(*this, client));
1878 }
1879
1880 LocationCapabilitiesMask
getCapabilities()1881 GnssAdapter::getCapabilities()
1882 {
1883 LocationCapabilitiesMask mask = 0;
1884 uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities();
1885 // time based tracking always supported
1886 mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT;
1887 // geofence always supported
1888 mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT;
1889 if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) {
1890 mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT;
1891 }
1892 if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) {
1893 mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT;
1894 }
1895 if (mLocApi == nullptr)
1896 return mask;
1897 if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) {
1898 mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT |
1899 LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT;
1900 }
1901 if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
1902 mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT;
1903 }
1904 if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) {
1905 mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT;
1906 }
1907 if (mLocApi->gnssConstellationConfig()) {
1908 mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT;
1909 }
1910 if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
1911 mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT;
1912 }
1913 if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1914 mask |= LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT;
1915 }
1916 if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
1917 mask |= LOCATION_CAPABILITIES_AGPM_BIT;
1918 }
1919 return mask;
1920 }
1921
1922 void
broadcastCapabilities(LocationCapabilitiesMask mask)1923 GnssAdapter::broadcastCapabilities(LocationCapabilitiesMask mask)
1924 {
1925 for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
1926 if (nullptr != it->second.capabilitiesCb) {
1927 it->second.capabilitiesCb(mask);
1928 }
1929 }
1930 }
1931
1932 LocationCallbacks
getClientCallbacks(LocationAPI * client)1933 GnssAdapter::getClientCallbacks(LocationAPI* client)
1934 {
1935 LocationCallbacks callbacks = {};
1936 auto it = mClientData.find(client);
1937 if (it != mClientData.end()) {
1938 callbacks = it->second;
1939 }
1940 return callbacks;
1941 }
1942
1943 void
saveClient(LocationAPI * client,const LocationCallbacks & callbacks)1944 GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks)
1945 {
1946 mClientData[client] = callbacks;
1947 updateClientsEventMask();
1948 }
1949
1950 void
eraseClient(LocationAPI * client)1951 GnssAdapter::eraseClient(LocationAPI* client)
1952 {
1953 auto it = mClientData.find(client);
1954 if (it != mClientData.end()) {
1955 mClientData.erase(it);
1956 }
1957 updateClientsEventMask();
1958 }
1959
1960 bool
hasTrackingCallback(LocationAPI * client)1961 GnssAdapter::hasTrackingCallback(LocationAPI* client)
1962 {
1963 auto it = mClientData.find(client);
1964 return (it != mClientData.end() && (it->second.trackingCb || it->second.gnssLocationInfoCb));
1965 }
1966
1967 bool
hasMeasurementsCallback(LocationAPI * client)1968 GnssAdapter::hasMeasurementsCallback(LocationAPI* client)
1969 {
1970 auto it = mClientData.find(client);
1971 return (it != mClientData.end() && it->second.gnssMeasurementsCb);
1972 }
1973
1974 bool
isTrackingSession(LocationAPI * client,uint32_t sessionId)1975 GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
1976 {
1977 LocationSessionKey key(client, sessionId);
1978 return (mTrackingSessions.find(key) != mTrackingSessions.end());
1979 }
1980
1981 void
saveTrackingSession(LocationAPI * client,uint32_t sessionId,const TrackingOptions & trackingOptions)1982 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
1983 const TrackingOptions& trackingOptions)
1984 {
1985 LocationSessionKey key(client, sessionId);
1986 mTrackingSessions[key] = trackingOptions;
1987 }
1988
1989 void
eraseTrackingSession(LocationAPI * client,uint32_t sessionId)1990 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
1991 {
1992 LocationSessionKey key(client, sessionId);
1993 auto itr = mTrackingSessions.find(key);
1994 if (itr != mTrackingSessions.end()) {
1995 mTrackingSessions.erase(itr);
1996 }
1997 }
1998
setUlpPositionMode(const LocPosMode & mode)1999 bool GnssAdapter::setUlpPositionMode(const LocPosMode& mode) {
2000 if (!mUlpPositionMode.equals(mode)) {
2001 mUlpPositionMode = mode;
2002 return true;
2003 } else {
2004 return false;
2005 }
2006 }
2007
2008 void
reportResponse(LocationAPI * client,LocationError err,uint32_t sessionId)2009 GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
2010 {
2011 LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
2012
2013 auto it = mClientData.find(client);
2014 if (it != mClientData.end() &&
2015 it->second.responseCb != nullptr) {
2016 it->second.responseCb(err, sessionId);
2017 } else {
2018 LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
2019 }
2020 }
2021
2022 void
reportResponse(LocationError err,uint32_t sessionId)2023 GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
2024 {
2025 LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
2026
2027 if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
2028 mControlCallbacks.responseCb(err, sessionId);
2029 } else {
2030 LOC_LOGW("%s]: control client response callback not found", __func__);
2031 }
2032 }
2033
2034 void
reportResponse(size_t count,LocationError * errs,uint32_t * ids)2035 GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
2036 {
2037 IF_LOC_LOGD {
2038 std::string idsString = "[";
2039 std::string errsString = "[";
2040 if (NULL != ids && NULL != errs) {
2041 for (size_t i=0; i < count; ++i) {
2042 idsString += std::to_string(ids[i]) + " ";
2043 errsString += std::to_string(errs[i]) + " ";
2044 }
2045 }
2046 idsString += "]";
2047 errsString += "]";
2048
2049 LOC_LOGD("%s]: ids %s errs %s",
2050 __func__, idsString.c_str(), errsString.c_str());
2051 }
2052
2053 if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
2054 mControlCallbacks.collectiveResponseCb(count, errs, ids);
2055 } else {
2056 LOC_LOGW("%s]: control client callback not found", __func__);
2057 }
2058 }
2059
2060 uint32_t
startTrackingCommand(LocationAPI * client,TrackingOptions & options)2061 GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options)
2062 {
2063 uint32_t sessionId = generateSessionId();
2064 LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u powermode %u tbm %u",
2065 __func__, client, sessionId, options.minInterval, options.minDistance, options.mode,
2066 options.powerMode, options.tbm);
2067
2068 struct MsgStartTracking : public LocMsg {
2069 GnssAdapter& mAdapter;
2070 LocApiBase& mApi;
2071 LocationAPI* mClient;
2072 uint32_t mSessionId;
2073 mutable TrackingOptions mTrackingOptions;
2074 inline MsgStartTracking(GnssAdapter& adapter,
2075 LocApiBase& api,
2076 LocationAPI* client,
2077 uint32_t sessionId,
2078 TrackingOptions trackingOptions) :
2079 LocMsg(),
2080 mAdapter(adapter),
2081 mApi(api),
2082 mClient(client),
2083 mSessionId(sessionId),
2084 mTrackingOptions(trackingOptions) {}
2085 inline virtual void proc() const {
2086 LocationError err = LOCATION_ERROR_SUCCESS;
2087 if (!mAdapter.hasTrackingCallback(mClient) &&
2088 !mAdapter.hasMeasurementsCallback(mClient)) {
2089 err = LOCATION_ERROR_CALLBACK_MISSING;
2090 } else if (0 == mTrackingOptions.size) {
2091 err = LOCATION_ERROR_INVALID_PARAMETER;
2092 } else {
2093 if (GNSS_POWER_MODE_INVALID != mTrackingOptions.powerMode &&
2094 !mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
2095 LOC_LOGv("Ignoring power mode, feature not supported.");
2096 mTrackingOptions.powerMode = GNSS_POWER_MODE_INVALID;
2097 }
2098 if (mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02) &&
2099 GNSS_POWER_MODE_M4 == mTrackingOptions.powerMode &&
2100 mTrackingOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2101 LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2102 mTrackingOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2103 mTrackingOptions.powerMode = GNSS_POWER_MODE_M2;
2104 }
2105 if (mTrackingOptions.minInterval < MIN_TRACKING_INTERVAL) {
2106 mTrackingOptions.minInterval = MIN_TRACKING_INTERVAL;
2107 }
2108 // Api doesn't support multiple clients for time based tracking, so mutiplex
2109 err = mAdapter.startTrackingMultiplex(mTrackingOptions);
2110 if (LOCATION_ERROR_SUCCESS == err) {
2111 mAdapter.saveTrackingSession(
2112 mClient, mSessionId, mTrackingOptions);
2113 }
2114 }
2115 mAdapter.reportResponse(mClient, err, mSessionId);
2116 }
2117 };
2118
2119 sendMsg(new MsgStartTracking(
2120 *this, *mLocApi, client, sessionId, options));
2121 return sessionId;
2122 }
2123
2124 LocationError
startTrackingMultiplex(const TrackingOptions & options)2125 GnssAdapter::startTrackingMultiplex(const TrackingOptions& options)
2126 {
2127 LocationError err = LOCATION_ERROR_SUCCESS;
2128
2129 if (mTrackingSessions.empty()) {
2130 err = startTracking(options);
2131 } else {
2132 // find the smallest interval and powerMode
2133 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2134 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2135 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
2136 // if not set or there is a new smallest interval, then set the new interval
2137 if (0 == multiplexedOptions.size ||
2138 it->second.minInterval < multiplexedOptions.minInterval) {
2139 multiplexedOptions = it->second;
2140 }
2141 // if session is not the one we are updating and either powerMode
2142 // is not set or there is a new smallest powerMode, then set the new powerMode
2143 if (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2144 it->second.powerMode < multiplexedPowerMode) {
2145 multiplexedPowerMode = it->second.powerMode;
2146 }
2147 }
2148 bool updateOptions = false;
2149 // if session we are starting has smaller interval then next smallest
2150 if (options.minInterval < multiplexedOptions.minInterval) {
2151 multiplexedOptions.minInterval = options.minInterval;
2152 updateOptions = true;
2153 }
2154 // if session we are starting has smaller powerMode then next smallest
2155 if (options.powerMode < multiplexedPowerMode) {
2156 multiplexedOptions.powerMode = options.powerMode;
2157 updateOptions = true;
2158 }
2159 if (updateOptions) {
2160 // restart time based tracking with the newly updated options
2161 err = startTracking(multiplexedOptions);
2162 }
2163 }
2164
2165 return err;
2166 }
2167
2168 LocationError
startTracking(const TrackingOptions & trackingOptions)2169 GnssAdapter::startTracking(const TrackingOptions& trackingOptions)
2170 {
2171 LOC_LOGd("minInterval %u minDistance %u mode %u powermode %u tbm %u",
2172 trackingOptions.minInterval, trackingOptions.minDistance,
2173 trackingOptions.mode, trackingOptions.powerMode, trackingOptions.tbm);
2174
2175 LocationError err = LOCATION_ERROR_SUCCESS;
2176 LocPosMode locPosMode = {};
2177 convertOptions(locPosMode, trackingOptions);
2178 if (!mUlpProxy->sendFixMode(locPosMode)) {
2179 // do nothing
2180 }
2181 if (!mUlpProxy->sendStartFix()) {
2182 loc_api_adapter_err apiErr = mLocApi->startFix(locPosMode);
2183 if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
2184 err = LOCATION_ERROR_SUCCESS;
2185 } else {
2186 err = LOCATION_ERROR_GENERAL_FAILURE;
2187 }
2188 }
2189
2190 return err;
2191 }
2192
2193 void
setPositionModeCommand(LocPosMode & locPosMode)2194 GnssAdapter::setPositionModeCommand(LocPosMode& locPosMode)
2195 {
2196 LOC_LOGD("%s]: min_interval %u mode %u",
2197 __func__, locPosMode.min_interval, locPosMode.mode);
2198
2199 struct MsgSetPositionMode : public LocMsg {
2200 GnssAdapter& mAdapter;
2201 LocApiBase& mApi;
2202 LocPosMode mLocPosMode;
2203 inline MsgSetPositionMode(GnssAdapter& adapter,
2204 LocApiBase& api,
2205 LocPosMode& locPosMode) :
2206 LocMsg(),
2207 mAdapter(adapter),
2208 mApi(api),
2209 mLocPosMode(locPosMode) {}
2210 inline virtual void proc() const {
2211 // saves the mode in adapter to be used when startTrackingCommand is called from ULP
2212 if (mAdapter.setUlpPositionMode(mLocPosMode)) {
2213 mApi.setPositionMode(mLocPosMode);
2214 }
2215 }
2216 };
2217
2218 sendMsg(new MsgSetPositionMode(*this, *mLocApi, locPosMode));
2219 }
2220
2221 void
startTrackingCommand()2222 GnssAdapter::startTrackingCommand()
2223 {
2224 LOC_LOGD("%s]: ", __func__);
2225
2226 struct MsgStartTracking : public LocMsg {
2227 GnssAdapter& mAdapter;
2228 LocApiBase& mApi;
2229 inline MsgStartTracking(GnssAdapter& adapter,
2230 LocApiBase& api) :
2231 LocMsg(),
2232 mAdapter(adapter),
2233 mApi(api) {}
2234 inline virtual void proc() const {
2235 // we get this call from ULP, so just call LocApi without multiplexing because
2236 // ulp would be doing the multiplexing for us if it is present
2237 if (!mAdapter.isInSession()) {
2238 LocPosMode& ulpPositionMode = mAdapter.getUlpPositionMode();
2239 mApi.startFix(ulpPositionMode);
2240 }
2241 }
2242 };
2243
2244 sendMsg(new MsgStartTracking(*this, *mLocApi));
2245 }
2246
2247 void
updateTrackingOptionsCommand(LocationAPI * client,uint32_t id,TrackingOptions & options)2248 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
2249 TrackingOptions& options)
2250 {
2251 LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
2252 __func__, client, id, options.minInterval, options.mode);
2253
2254 struct MsgUpdateTracking : public LocMsg {
2255 GnssAdapter& mAdapter;
2256 LocApiBase& mApi;
2257 LocationAPI* mClient;
2258 uint32_t mSessionId;
2259 mutable TrackingOptions mTrackingOptions;
2260 inline MsgUpdateTracking(GnssAdapter& adapter,
2261 LocApiBase& api,
2262 LocationAPI* client,
2263 uint32_t sessionId,
2264 TrackingOptions trackingOptions) :
2265 LocMsg(),
2266 mAdapter(adapter),
2267 mApi(api),
2268 mClient(client),
2269 mSessionId(sessionId),
2270 mTrackingOptions(trackingOptions) {}
2271 inline virtual void proc() const {
2272 if (mAdapter.isTrackingSession(mClient, mSessionId)) {
2273 LocationError err = LOCATION_ERROR_SUCCESS;
2274 if (0 == mTrackingOptions.size) {
2275 err = LOCATION_ERROR_INVALID_PARAMETER;
2276 } else {
2277 if (GNSS_POWER_MODE_INVALID != mTrackingOptions.powerMode &&
2278 !mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
2279 LOC_LOGv("Ignoring power mode, feature not supported.");
2280 mTrackingOptions.powerMode = GNSS_POWER_MODE_INVALID;
2281 }
2282 if (mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02) &&
2283 GNSS_POWER_MODE_M4 == mTrackingOptions.powerMode &&
2284 mTrackingOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2285 LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2286 mTrackingOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2287 mTrackingOptions.powerMode = GNSS_POWER_MODE_M2;
2288 }
2289 if (mTrackingOptions.minInterval < MIN_TRACKING_INTERVAL) {
2290 mTrackingOptions.minInterval = MIN_TRACKING_INTERVAL;
2291 }
2292 // Api doesn't support multiple clients for time based tracking, so mutiplex
2293 err = mAdapter.updateTrackingMultiplex(
2294 mClient, mSessionId, mTrackingOptions);
2295 if (LOCATION_ERROR_SUCCESS == err) {
2296 mAdapter.saveTrackingSession(
2297 mClient, mSessionId, mTrackingOptions);
2298 }
2299 }
2300 mAdapter.reportResponse(mClient, err, mSessionId);
2301 }
2302 // we do not reportResponse for the case where there is no existing tracking session
2303 // for the client and id being used, since updateTrackingCommand can be sent to both
2304 // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
2305 }
2306 };
2307
2308 sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
2309 }
2310
2311 LocationError
updateTrackingMultiplex(LocationAPI * client,uint32_t id,const TrackingOptions & trackingOptions)2312 GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
2313 const TrackingOptions& trackingOptions)
2314 {
2315 LocationError err = LOCATION_ERROR_SUCCESS;
2316
2317 LocationSessionKey key(client, id);
2318
2319 // get the session we are updating
2320 auto it = mTrackingSessions.find(key);
2321 // if session we are updating exists and the minInterval or powerMode has changed
2322 if (it != mTrackingSessions.end() && (it->second.minInterval != trackingOptions.minInterval ||
2323 it->second.powerMode != trackingOptions.powerMode)) {
2324 // find the smallest interval and powerMode, other than the session we are updating
2325 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2326 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2327 for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
2328 // if session is not the one we are updating and either interval
2329 // is not set or there is a new smallest interval, then set the new interval
2330 if (it2->first != key && (0 == multiplexedOptions.size ||
2331 it2->second.minInterval < multiplexedOptions.minInterval)) {
2332 multiplexedOptions = it2->second;
2333 }
2334 // if session is not the one we are updating and either powerMode
2335 // is not set or there is a new smallest powerMode, then set the new powerMode
2336 if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2337 it2->second.powerMode < multiplexedPowerMode)) {
2338 multiplexedPowerMode = it2->second.powerMode;
2339 }
2340 }
2341 bool updateOptions = false;
2342 // if session we are updating has smaller interval then next smallest
2343 if (trackingOptions.minInterval < multiplexedOptions.minInterval) {
2344 multiplexedOptions.minInterval = trackingOptions.minInterval;
2345 updateOptions = true;
2346 }
2347 // if session we are updating has smaller powerMode then next smallest
2348 if (trackingOptions.powerMode < multiplexedPowerMode) {
2349 multiplexedOptions.powerMode = trackingOptions.powerMode;
2350 updateOptions = true;
2351 }
2352 // if only one session exists, then tracking should be updated with it
2353 if (1 == mTrackingSessions.size()) {
2354 multiplexedOptions = trackingOptions;
2355 updateOptions = true;
2356 }
2357 if (updateOptions) {
2358 // restart time based tracking with the newly updated options
2359 err = startTracking(multiplexedOptions);
2360 }
2361 }
2362
2363 return err;
2364 }
2365
2366 void
stopTrackingCommand(LocationAPI * client,uint32_t id)2367 GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
2368 {
2369 LOC_LOGD("%s]: client %p id %u", __func__, client, id);
2370
2371 struct MsgStopTracking : public LocMsg {
2372 GnssAdapter& mAdapter;
2373 LocApiBase& mApi;
2374 LocationAPI* mClient;
2375 uint32_t mSessionId;
2376 inline MsgStopTracking(GnssAdapter& adapter,
2377 LocApiBase& api,
2378 LocationAPI* client,
2379 uint32_t sessionId) :
2380 LocMsg(),
2381 mAdapter(adapter),
2382 mApi(api),
2383 mClient(client),
2384 mSessionId(sessionId) {}
2385 inline virtual void proc() const {
2386 if (mAdapter.isTrackingSession(mClient, mSessionId)) {
2387 LocationError err = LOCATION_ERROR_SUCCESS;
2388 // Api doesn't support multiple clients for time based tracking, so mutiplex
2389 err = mAdapter.stopTrackingMultiplex(mClient, mSessionId);
2390 if (LOCATION_ERROR_SUCCESS == err) {
2391 mAdapter.eraseTrackingSession(mClient, mSessionId);
2392 }
2393 mAdapter.reportResponse(mClient, err, mSessionId);
2394 }
2395 // we do not reportResponse for the case where there is no existing tracking session
2396 // for the client and id being used, since stopTrackingCommand can be sent to both
2397 // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
2398
2399 }
2400 };
2401
2402 sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
2403 }
2404
2405 LocationError
stopTrackingMultiplex(LocationAPI * client,uint32_t id)2406 GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id)
2407 {
2408 LocationError err = LOCATION_ERROR_SUCCESS;
2409
2410 if (1 == mTrackingSessions.size()) {
2411 err = stopTracking();
2412 } else {
2413 LocationSessionKey key(client, id);
2414
2415 // get the session we are stopping
2416 auto it = mTrackingSessions.find(key);
2417 if (it != mTrackingSessions.end()) {
2418 // find the smallest interval and powerMode, other than the session we are stopping
2419 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2420 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2421 for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
2422 // if session is not the one we are stopping and either interval
2423 // is not set or there is a new smallest interval, then set the new interval
2424 if (it2->first != key && (0 == multiplexedOptions.size ||
2425 it2->second.minInterval < multiplexedOptions.minInterval)) {
2426 multiplexedOptions = it2->second;
2427 }
2428 // if session is not the one we are stopping and either powerMode
2429 // is not set or there is a new smallest powerMode, then set the new powerMode
2430 if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2431 it2->second.powerMode < multiplexedPowerMode)) {
2432 multiplexedPowerMode = it2->second.powerMode;
2433 }
2434 }
2435 // if session we are stopping has smaller interval then next smallest or
2436 // if session we are stopping has smaller powerMode then next smallest
2437 if (it->second.minInterval < multiplexedOptions.minInterval ||
2438 it->second.powerMode < multiplexedPowerMode) {
2439 multiplexedOptions.powerMode = multiplexedPowerMode;
2440 // restart time based tracking with the newly updated options
2441 err = startTracking(multiplexedOptions);
2442 }
2443 }
2444 }
2445
2446 return err;
2447 }
2448
2449 LocationError
stopTracking()2450 GnssAdapter::stopTracking()
2451 {
2452 LocationError err = LOCATION_ERROR_SUCCESS;
2453 if (!mUlpProxy->sendStopFix()) {
2454 loc_api_adapter_err apiErr = mLocApi->stopFix();
2455 if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
2456 err = LOCATION_ERROR_SUCCESS;
2457 } else {
2458 err = LOCATION_ERROR_GENERAL_FAILURE;
2459 }
2460 }
2461
2462 return err;
2463 }
2464
2465 void
stopTrackingCommand()2466 GnssAdapter::stopTrackingCommand()
2467 {
2468 LOC_LOGD("%s]: ", __func__);
2469
2470 struct MsgStopTracking : public LocMsg {
2471 GnssAdapter& mAdapter;
2472 LocApiBase& mApi;
2473 inline MsgStopTracking(GnssAdapter& adapter,
2474 LocApiBase& api) :
2475 LocMsg(),
2476 mAdapter(adapter),
2477 mApi(api) {}
2478 inline virtual void proc() const {
2479 // clear the position mode
2480 LocPosMode mLocPosMode = {};
2481 mLocPosMode.mode = LOC_POSITION_MODE_INVALID;
2482 mAdapter.setUlpPositionMode(mLocPosMode);
2483 // don't need to multiplex because ULP will do that for us if it is present
2484 mApi.stopFix();
2485 }
2486 };
2487
2488 sendMsg(new MsgStopTracking(*this, *mLocApi));
2489 }
2490
2491 void
getZppCommand()2492 GnssAdapter::getZppCommand()
2493 {
2494 LOC_LOGD("%s]: ", __func__);
2495
2496 struct MsgGetZpp : public LocMsg {
2497 GnssAdapter& mAdapter;
2498 LocApiBase& mApi;
2499 inline MsgGetZpp(GnssAdapter& adapter,
2500 LocApiBase& api) :
2501 LocMsg(),
2502 mAdapter(adapter),
2503 mApi(api) {}
2504 inline virtual void proc() const {
2505 UlpLocation location = {};
2506 LocPosTechMask techMask = LOC_POS_TECH_MASK_DEFAULT;
2507 GpsLocationExtended locationExtended = {};
2508 locationExtended.size = sizeof(locationExtended);
2509
2510 mApi.getBestAvailableZppFix(location.gpsLocation, locationExtended,
2511 techMask);
2512 //Mark the location source as from ZPP
2513 location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO;
2514 location.position_source = ULP_LOCATION_IS_FROM_ZPP;
2515
2516 mAdapter.getUlpProxy()->reportPosition(location,
2517 locationExtended,
2518 LOC_SESS_SUCCESS,
2519 techMask);
2520 }
2521 };
2522
2523 sendMsg(new MsgGetZpp(*this, *mLocApi));
2524 }
2525
2526 bool
hasNiNotifyCallback(LocationAPI * client)2527 GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
2528 {
2529 auto it = mClientData.find(client);
2530 return (it != mClientData.end() && it->second.gnssNiCb);
2531 }
2532
2533 void
gnssNiResponseCommand(LocationAPI * client,uint32_t id,GnssNiResponse response)2534 GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
2535 uint32_t id,
2536 GnssNiResponse response)
2537 {
2538 LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
2539
2540 struct MsgGnssNiResponse : public LocMsg {
2541 GnssAdapter& mAdapter;
2542 LocationAPI* mClient;
2543 uint32_t mSessionId;
2544 GnssNiResponse mResponse;
2545 inline MsgGnssNiResponse(GnssAdapter& adapter,
2546 LocationAPI* client,
2547 uint32_t sessionId,
2548 GnssNiResponse response) :
2549 LocMsg(),
2550 mAdapter(adapter),
2551 mClient(client),
2552 mSessionId(sessionId),
2553 mResponse(response) {}
2554 inline virtual void proc() const {
2555 NiData& niData = mAdapter.getNiData();
2556 LocationError err = LOCATION_ERROR_SUCCESS;
2557 if (!mAdapter.hasNiNotifyCallback(mClient)) {
2558 err = LOCATION_ERROR_ID_UNKNOWN;
2559 } else {
2560 NiSession* pSession = NULL;
2561 if (mSessionId == niData.sessionEs.reqID &&
2562 NULL != niData.sessionEs.rawRequest) {
2563 pSession = &niData.sessionEs;
2564 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
2565 if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
2566 NULL != niData.session.rawRequest) {
2567 pthread_mutex_lock(&niData.session.tLock);
2568 niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
2569 niData.session.respRecvd = true;
2570 pthread_cond_signal(&niData.session.tCond);
2571 pthread_mutex_unlock(&niData.session.tLock);
2572 }
2573 } else if (mSessionId == niData.session.reqID &&
2574 NULL != niData.session.rawRequest) {
2575 pSession = &niData.session;
2576 }
2577
2578 if (pSession) {
2579 LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
2580 __func__, mResponse, mSessionId);
2581 pthread_mutex_lock(&pSession->tLock);
2582 pSession->resp = mResponse;
2583 pSession->respRecvd = true;
2584 pthread_cond_signal(&pSession->tCond);
2585 pthread_mutex_unlock(&pSession->tLock);
2586 } else {
2587 err = LOCATION_ERROR_ID_UNKNOWN;
2588 LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
2589 __func__, mSessionId);
2590 }
2591 }
2592 mAdapter.reportResponse(mClient, err, mSessionId);
2593 }
2594 };
2595
2596 sendMsg(new MsgGnssNiResponse(*this, client, id, response));
2597
2598 }
2599
2600 void
gnssNiResponseCommand(GnssNiResponse response,void * rawRequest)2601 GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
2602 {
2603 LOC_LOGD("%s]: response %u", __func__, response);
2604
2605 struct MsgGnssNiResponse : public LocMsg {
2606 LocApiBase& mApi;
2607 const GnssNiResponse mResponse;
2608 const void* mPayload;
2609 inline MsgGnssNiResponse(LocApiBase& api,
2610 const GnssNiResponse response,
2611 const void* rawRequest) :
2612 LocMsg(),
2613 mApi(api),
2614 mResponse(response),
2615 mPayload(rawRequest) {}
2616 inline virtual ~MsgGnssNiResponse() {
2617 // this is a bit weird since mPayload is not
2618 // allocated by this class. But there is no better way.
2619 // mPayload actually won't be NULL here.
2620 free((void*)mPayload);
2621 }
2622 inline virtual void proc() const {
2623 mApi.informNiResponse(mResponse, mPayload);
2624 }
2625 };
2626
2627 sendMsg(new MsgGnssNiResponse(*mLocApi, response, rawRequest));
2628
2629 }
2630
2631 uint32_t
enableCommand(LocationTechnologyType techType)2632 GnssAdapter::enableCommand(LocationTechnologyType techType)
2633 {
2634 uint32_t sessionId = generateSessionId();
2635 LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
2636
2637 struct MsgEnableGnss : public LocMsg {
2638 GnssAdapter& mAdapter;
2639 LocApiBase& mApi;
2640 ContextBase& mContext;
2641 uint32_t mSessionId;
2642 LocationTechnologyType mTechType;
2643 inline MsgEnableGnss(GnssAdapter& adapter,
2644 LocApiBase& api,
2645 ContextBase& context,
2646 uint32_t sessionId,
2647 LocationTechnologyType techType) :
2648 LocMsg(),
2649 mAdapter(adapter),
2650 mApi(api),
2651 mContext(context),
2652 mSessionId(sessionId),
2653 mTechType(techType) {}
2654 inline virtual void proc() const {
2655 LocationError err = LOCATION_ERROR_SUCCESS;
2656 uint32_t powerVoteId = mAdapter.getPowerVoteId();
2657 if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
2658 err = LOCATION_ERROR_INVALID_PARAMETER;
2659 } else if (powerVoteId > 0) {
2660 err = LOCATION_ERROR_ALREADY_STARTED;
2661 } else {
2662 mContext.modemPowerVote(true);
2663 mAdapter.setPowerVoteId(mSessionId);
2664 mApi.setGpsLock(GNSS_CONFIG_GPS_LOCK_NONE);
2665 mAdapter.mXtraObserver.updateLockStatus(
2666 mAdapter.convertGpsLock(GNSS_CONFIG_GPS_LOCK_NONE));
2667 }
2668 mAdapter.reportResponse(err, mSessionId);
2669 }
2670 };
2671
2672 if (mContext != NULL) {
2673 sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
2674 } else {
2675 LOC_LOGE("%s]: Context is NULL", __func__);
2676 }
2677
2678 return sessionId;
2679 }
2680
2681 void
disableCommand(uint32_t id)2682 GnssAdapter::disableCommand(uint32_t id)
2683 {
2684 LOC_LOGD("%s]: id %u", __func__, id);
2685
2686 struct MsgDisableGnss : public LocMsg {
2687 GnssAdapter& mAdapter;
2688 LocApiBase& mApi;
2689 ContextBase& mContext;
2690 uint32_t mSessionId;
2691 inline MsgDisableGnss(GnssAdapter& adapter,
2692 LocApiBase& api,
2693 ContextBase& context,
2694 uint32_t sessionId) :
2695 LocMsg(),
2696 mAdapter(adapter),
2697 mApi(api),
2698 mContext(context),
2699 mSessionId(sessionId) {}
2700 inline virtual void proc() const {
2701 LocationError err = LOCATION_ERROR_SUCCESS;
2702 uint32_t powerVoteId = mAdapter.getPowerVoteId();
2703 if (powerVoteId != mSessionId) {
2704 err = LOCATION_ERROR_ID_UNKNOWN;
2705 } else {
2706 mContext.modemPowerVote(false);
2707 mAdapter.setPowerVoteId(0);
2708 mApi.setGpsLock(mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK));
2709 mAdapter.mXtraObserver.updateLockStatus(
2710 mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK));
2711 }
2712 mAdapter.reportResponse(err, mSessionId);
2713 }
2714 };
2715
2716 if (mContext != NULL) {
2717 sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
2718 }
2719
2720 }
2721
2722 void
reportPositionEvent(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask,bool fromUlp)2723 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
2724 const GpsLocationExtended& locationExtended,
2725 enum loc_sess_status status,
2726 LocPosTechMask techMask,
2727 bool fromUlp)
2728 {
2729 LOC_LOGD("%s]: fromUlp %u status %u", __func__, fromUlp, status);
2730
2731 // if this event is not called from ULP, then try to call into ULP and return if successfull
2732 if (!fromUlp) {
2733 if (mUlpProxy->reportPosition(ulpLocation, locationExtended,
2734 status, techMask)) {
2735 return;
2736 }
2737 }
2738
2739 struct MsgReportPosition : public LocMsg {
2740 GnssAdapter& mAdapter;
2741 const UlpLocation mUlpLocation;
2742 const GpsLocationExtended mLocationExtended;
2743 loc_sess_status mStatus;
2744 LocPosTechMask mTechMask;
2745 inline MsgReportPosition(GnssAdapter& adapter,
2746 const UlpLocation& ulpLocation,
2747 const GpsLocationExtended& locationExtended,
2748 loc_sess_status status,
2749 LocPosTechMask techMask) :
2750 LocMsg(),
2751 mAdapter(adapter),
2752 mUlpLocation(ulpLocation),
2753 mLocationExtended(locationExtended),
2754 mStatus(status),
2755 mTechMask(techMask) {}
2756 inline virtual void proc() const {
2757 // extract bug report info - this returns true if consumed by systemstatus
2758 SystemStatus* s = mAdapter.getSystemStatus();
2759 if ((nullptr != s) &&
2760 ((LOC_SESS_SUCCESS == mStatus) || (LOC_SESS_INTERMEDIATE == mStatus))){
2761 s->eventPosition(mUlpLocation, mLocationExtended);
2762 }
2763 mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
2764 }
2765 };
2766
2767 sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended, status, techMask));
2768 }
2769
2770 bool
needReport(const UlpLocation & ulpLocation,enum loc_sess_status status,LocPosTechMask techMask)2771 GnssAdapter::needReport(const UlpLocation& ulpLocation,
2772 enum loc_sess_status status,
2773 LocPosTechMask techMask) {
2774 bool reported = false;
2775
2776 reported = LocApiBase::needReport(ulpLocation, status, techMask);
2777 return reported;
2778 }
2779
2780 void
reportPosition(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask)2781 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
2782 const GpsLocationExtended& locationExtended,
2783 enum loc_sess_status status,
2784 LocPosTechMask techMask)
2785 {
2786 bool reported = needReport(ulpLocation, status, techMask);
2787 mGnssSvIdUsedInPosAvail = false;
2788 if (reported) {
2789 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
2790 mGnssSvIdUsedInPosAvail = true;
2791 mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
2792 }
2793
2794 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2795 if (nullptr != it->second.gnssLocationInfoCb) {
2796 GnssLocationInfoNotification locationInfo = {};
2797 convertLocationInfo(locationInfo, locationExtended);
2798 convertLocation(locationInfo.location, ulpLocation, locationExtended, techMask);
2799 it->second.gnssLocationInfoCb(locationInfo);
2800 } else if (nullptr != it->second.trackingCb) {
2801 Location location = {};
2802 convertLocation(location, ulpLocation, locationExtended, techMask);
2803 it->second.trackingCb(location);
2804 }
2805 }
2806 }
2807
2808 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
2809 /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 &
2810 horReliability is not set. */
2811 bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) &&
2812 (0 == ulpLocation.gpsLocation.longitude) &&
2813 (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability));
2814 uint8_t generate_nmea = (reported && status != LOC_SESS_FAILURE && !blank_fix);
2815 std::vector<std::string> nmeaArraystr;
2816 loc_nmea_generate_pos(ulpLocation, locationExtended, generate_nmea, nmeaArraystr);
2817 for (auto sentence : nmeaArraystr) {
2818 reportNmea(sentence.c_str(), sentence.length());
2819 }
2820 }
2821 }
2822
2823 void
reportSvEvent(const GnssSvNotification & svNotify,bool fromUlp)2824 GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
2825 bool fromUlp)
2826 {
2827 LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp);
2828
2829 // if this event is not called from ULP, then try to call into ULP and return if successfull
2830 if (!fromUlp) {
2831 if (mUlpProxy->reportSv(svNotify)) {
2832 return;
2833 }
2834 }
2835
2836 struct MsgReportSv : public LocMsg {
2837 GnssAdapter& mAdapter;
2838 const GnssSvNotification mSvNotify;
2839 inline MsgReportSv(GnssAdapter& adapter,
2840 const GnssSvNotification& svNotify) :
2841 LocMsg(),
2842 mAdapter(adapter),
2843 mSvNotify(svNotify) {}
2844 inline virtual void proc() const {
2845 mAdapter.reportSv((GnssSvNotification&)mSvNotify);
2846 }
2847 };
2848
2849 sendMsg(new MsgReportSv(*this, svNotify));
2850 }
2851
2852 void
reportSv(GnssSvNotification & svNotify)2853 GnssAdapter::reportSv(GnssSvNotification& svNotify)
2854 {
2855 int numSv = svNotify.count;
2856 int16_t gnssSvId = 0;
2857 uint64_t svUsedIdMask = 0;
2858 for (int i=0; i < numSv; i++) {
2859 svUsedIdMask = 0;
2860 gnssSvId = svNotify.gnssSvs[i].svId;
2861 switch (svNotify.gnssSvs[i].type) {
2862 case GNSS_SV_TYPE_GPS:
2863 if (mGnssSvIdUsedInPosAvail) {
2864 svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
2865 }
2866 break;
2867 case GNSS_SV_TYPE_GLONASS:
2868 if (mGnssSvIdUsedInPosAvail) {
2869 svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
2870 }
2871 break;
2872 case GNSS_SV_TYPE_BEIDOU:
2873 if (mGnssSvIdUsedInPosAvail) {
2874 svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
2875 }
2876 break;
2877 case GNSS_SV_TYPE_GALILEO:
2878 if (mGnssSvIdUsedInPosAvail) {
2879 svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
2880 }
2881 break;
2882 case GNSS_SV_TYPE_QZSS:
2883 if (mGnssSvIdUsedInPosAvail) {
2884 svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
2885 }
2886 // QZSS SV id's need to reported as it is to framework, since
2887 // framework expects it as it is. See GnssStatus.java.
2888 // SV id passed to here by LocApi is 1-based.
2889 svNotify.gnssSvs[i].svId += (QZSS_SV_PRN_MIN - 1);
2890 break;
2891 default:
2892 svUsedIdMask = 0;
2893 break;
2894 }
2895
2896 // If SV ID was used in previous position fix, then set USED_IN_FIX
2897 // flag, else clear the USED_IN_FIX flag.
2898 if (svUsedIdMask & (1 << (gnssSvId - 1))) {
2899 svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
2900 }
2901 }
2902
2903 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2904 if (nullptr != it->second.gnssSvCb) {
2905 it->second.gnssSvCb(svNotify);
2906 }
2907 }
2908
2909 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
2910 std::vector<std::string> nmeaArraystr;
2911 loc_nmea_generate_sv(svNotify, nmeaArraystr);
2912 for (auto sentence : nmeaArraystr) {
2913 reportNmea(sentence.c_str(), sentence.length());
2914 }
2915 }
2916
2917 mGnssSvIdUsedInPosAvail = false;
2918 }
2919
2920 void
reportNmeaEvent(const char * nmea,size_t length,bool fromUlp)2921 GnssAdapter::reportNmeaEvent(const char* nmea, size_t length, bool fromUlp)
2922 {
2923 // if this event is not called from ULP, then try to call into ULP and return if successfull
2924 if (!fromUlp && !loc_nmea_is_debug(nmea, length)) {
2925 if (mUlpProxy->reportNmea(nmea, length)) {
2926 return;
2927 }
2928 }
2929
2930 struct MsgReportNmea : public LocMsg {
2931 GnssAdapter& mAdapter;
2932 const char* mNmea;
2933 size_t mLength;
2934 inline MsgReportNmea(GnssAdapter& adapter,
2935 const char* nmea,
2936 size_t length) :
2937 LocMsg(),
2938 mAdapter(adapter),
2939 mNmea(new char[length+1]),
2940 mLength(length) {
2941 if (mNmea == nullptr) {
2942 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
2943 return;
2944 }
2945 strlcpy((char*)mNmea, nmea, length+1);
2946 }
2947 inline virtual ~MsgReportNmea()
2948 {
2949 delete[] mNmea;
2950 }
2951 inline virtual void proc() const {
2952 // extract bug report info - this returns true if consumed by systemstatus
2953 bool ret = false;
2954 SystemStatus* s = mAdapter.getSystemStatus();
2955 if (nullptr != s) {
2956 ret = s->setNmeaString(mNmea, mLength);
2957 }
2958 if (false == ret) {
2959 // forward NMEA message to upper layer
2960 mAdapter.reportNmea(mNmea, mLength);
2961 }
2962 }
2963 };
2964
2965 sendMsg(new MsgReportNmea(*this, nmea, length));
2966 }
2967
2968 void
reportNmea(const char * nmea,size_t length)2969 GnssAdapter::reportNmea(const char* nmea, size_t length)
2970 {
2971 GnssNmeaNotification nmeaNotification = {};
2972 nmeaNotification.size = sizeof(GnssNmeaNotification);
2973
2974 struct timeval tv;
2975 gettimeofday(&tv, (struct timezone *) NULL);
2976 int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
2977 nmeaNotification.timestamp = now;
2978 nmeaNotification.nmea = nmea;
2979 nmeaNotification.length = length;
2980
2981 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2982 if (nullptr != it->second.gnssNmeaCb) {
2983 it->second.gnssNmeaCb(nmeaNotification);
2984 }
2985 }
2986 }
2987
2988 bool
requestNiNotifyEvent(const GnssNiNotification & notify,const void * data)2989 GnssAdapter::requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* data)
2990 {
2991 LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
2992 "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
2993 __func__, notify.type, notify.timeout, notify.timeoutResponse,
2994 notify.requestor, notify.requestorEncoding,
2995 notify.message, notify.messageEncoding, notify.extras);
2996
2997 struct MsgReportNiNotify : public LocMsg {
2998 GnssAdapter& mAdapter;
2999 const GnssNiNotification mNotify;
3000 const void* mData;
3001 inline MsgReportNiNotify(GnssAdapter& adapter,
3002 const GnssNiNotification& notify,
3003 const void* data) :
3004 LocMsg(),
3005 mAdapter(adapter),
3006 mNotify(notify),
3007 mData(data) {}
3008 inline virtual void proc() const {
3009 mAdapter.requestNiNotify(mNotify, mData);
3010 }
3011 };
3012
3013 sendMsg(new MsgReportNiNotify(*this, notify, data));
3014
3015 return true;
3016 }
3017
niThreadProc(void * args)3018 static void* niThreadProc(void *args)
3019 {
3020 NiSession* pSession = (NiSession*)args;
3021 int rc = 0; /* return code from pthread calls */
3022
3023 struct timespec present_time;
3024 struct timespec expire_time;
3025
3026 pthread_mutex_lock(&pSession->tLock);
3027 /* Calculate absolute expire time */
3028 clock_gettime(CLOCK_MONOTONIC, &present_time);
3029 expire_time.tv_sec = present_time.tv_sec + pSession->respTimeLeft;
3030 expire_time.tv_nsec = present_time.tv_nsec;
3031 LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
3032 __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
3033
3034 while (!pSession->respRecvd) {
3035 rc = pthread_cond_timedwait(&pSession->tCond,
3036 &pSession->tLock,
3037 &expire_time);
3038 if (rc == ETIMEDOUT) {
3039 pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
3040 LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
3041 __func__, rc);
3042 break;
3043 }
3044 }
3045 LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
3046 "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
3047 pSession->respRecvd = false; /* Reset the user response flag for the next session*/
3048
3049 // adding this check to support modem restart, in which case, we need the thread
3050 // to exit without calling sending data. We made sure that rawRequest is NULL in
3051 // loc_eng_ni_reset_on_engine_restart()
3052 GnssAdapter* adapter = pSession->adapter;
3053 GnssNiResponse resp;
3054 void* rawRequest = NULL;
3055 bool sendResponse = false;
3056
3057 if (NULL != pSession->rawRequest) {
3058 if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
3059 resp = pSession->resp;
3060 rawRequest = pSession->rawRequest;
3061 sendResponse = true;
3062 } else {
3063 free(pSession->rawRequest);
3064 }
3065 pSession->rawRequest = NULL;
3066 }
3067 pthread_mutex_unlock(&pSession->tLock);
3068
3069 pSession->respTimeLeft = 0;
3070 pSession->reqID = 0;
3071
3072 if (sendResponse) {
3073 adapter->gnssNiResponseCommand(resp, rawRequest);
3074 }
3075
3076 return NULL;
3077 }
3078
3079 bool
requestNiNotify(const GnssNiNotification & notify,const void * data)3080 GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data)
3081 {
3082 NiSession* pSession = NULL;
3083 gnssNiCallback gnssNiCb = nullptr;
3084
3085 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3086 if (nullptr != it->second.gnssNiCb) {
3087 gnssNiCb = it->second.gnssNiCb;
3088 break;
3089 }
3090 }
3091 if (nullptr == gnssNiCb) {
3092 EXIT_LOG(%s, "no clients with gnssNiCb.");
3093 return false;
3094 }
3095
3096 if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
3097 if (NULL != mNiData.sessionEs.rawRequest) {
3098 LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
3099 __func__, notify.type);
3100 if (NULL != data) {
3101 free((void*)data);
3102 }
3103 } else {
3104 pSession = &mNiData.sessionEs;
3105 }
3106 } else {
3107 if (NULL != mNiData.session.rawRequest ||
3108 NULL != mNiData.sessionEs.rawRequest) {
3109 LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
3110 __func__, notify.type);
3111 if (NULL != data) {
3112 free((void*)data);
3113 }
3114 } else {
3115 pSession = &mNiData.session;
3116 }
3117 }
3118
3119 if (pSession) {
3120 /* Save request */
3121 pSession->rawRequest = (void*)data;
3122 pSession->reqID = ++mNiData.reqIDCounter;
3123 pSession->adapter = this;
3124
3125 int sessionId = pSession->reqID;
3126
3127 /* For robustness, spawn a thread at this point to timeout to clear up the notification
3128 * status, even though the OEM layer in java does not do so.
3129 **/
3130 pSession->respTimeLeft =
3131 5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
3132
3133 int rc = 0;
3134 rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
3135 if (rc) {
3136 LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
3137 }
3138 rc = pthread_detach(pSession->thread);
3139 if (rc) {
3140 LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
3141 }
3142
3143 if (nullptr != gnssNiCb) {
3144 gnssNiCb(sessionId, notify);
3145 }
3146 }
3147
3148 return true;
3149 }
3150
3151 void
reportGnssMeasurementDataEvent(const GnssMeasurementsNotification & measurements,int msInWeek)3152 GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements,
3153 int msInWeek)
3154 {
3155 LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek);
3156
3157 struct MsgReportGnssMeasurementData : public LocMsg {
3158 GnssAdapter& mAdapter;
3159 GnssMeasurementsNotification mMeasurementsNotify;
3160 inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
3161 const GnssMeasurementsNotification& measurements,
3162 int msInWeek) :
3163 LocMsg(),
3164 mAdapter(adapter),
3165 mMeasurementsNotify(measurements) {
3166 if (-1 != msInWeek) {
3167 mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek);
3168 }
3169 }
3170 inline virtual void proc() const {
3171 mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
3172 }
3173 };
3174
3175 sendMsg(new MsgReportGnssMeasurementData(*this, measurements, msInWeek));
3176 }
3177
3178 void
reportGnssMeasurementData(const GnssMeasurementsNotification & measurements)3179 GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurements)
3180 {
3181 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3182 if (nullptr != it->second.gnssMeasurementsCb) {
3183 it->second.gnssMeasurementsCb(measurements);
3184 }
3185 }
3186 }
3187
3188 void
reportSvMeasurementEvent(GnssSvMeasurementSet & svMeasurementSet)3189 GnssAdapter::reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet)
3190 {
3191 LOC_LOGD("%s]: ", __func__);
3192
3193 // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
3194 mUlpProxy->reportSvMeasurement(svMeasurementSet);
3195 }
3196
3197 void
reportSvPolynomialEvent(GnssSvPolynomial & svPolynomial)3198 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
3199 {
3200 LOC_LOGD("%s]: ", __func__);
3201
3202 // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
3203 mUlpProxy->reportSvPolynomial(svPolynomial);
3204 }
3205
3206 bool
reportOdcpiRequestEvent(OdcpiRequestInfo & request)3207 GnssAdapter::reportOdcpiRequestEvent(OdcpiRequestInfo& request)
3208 {
3209 struct MsgReportOdcpiRequest : public LocMsg {
3210 GnssAdapter& mAdapter;
3211 OdcpiRequestInfo mOdcpiRequest;
3212 inline MsgReportOdcpiRequest(GnssAdapter& adapter, OdcpiRequestInfo& request) :
3213 LocMsg(),
3214 mAdapter(adapter),
3215 mOdcpiRequest(request) {}
3216 inline virtual void proc() const {
3217 mAdapter.reportOdcpiRequest(mOdcpiRequest);
3218 }
3219 };
3220
3221 sendMsg(new MsgReportOdcpiRequest(*this, request));
3222 return true;
3223 }
3224
reportOdcpiRequest(const OdcpiRequestInfo & request)3225 void GnssAdapter::reportOdcpiRequest(const OdcpiRequestInfo& request)
3226 {
3227 if (nullptr != mOdcpiRequestCb) {
3228 LOC_LOGd("request: type %d, tbf %d, isEmergency %d"
3229 " requestActive: %d timerActive: %d",
3230 request.type, request.tbfMillis, request.isEmergencyMode,
3231 mOdcpiRequestActive, mOdcpiTimer.isActive());
3232 // ODCPI START and ODCPI STOP from modem can come in quick succession
3233 // so the mOdcpiTimer helps avoid spamming the framework as well as
3234 // extending the odcpi session past 30 seconds if needed
3235 if (ODCPI_REQUEST_TYPE_START == request.type) {
3236 if (false == mOdcpiRequestActive && false == mOdcpiTimer.isActive()) {
3237 mOdcpiRequestCb(request);
3238 mOdcpiRequestActive = true;
3239 mOdcpiTimer.start();
3240 // if the current active odcpi session is non-emergency, and the new
3241 // odcpi request is emergency, replace the odcpi request with new request
3242 // and restart the timer
3243 } else if (false == mOdcpiRequest.isEmergencyMode &&
3244 true == request.isEmergencyMode) {
3245 mOdcpiRequestCb(request);
3246 mOdcpiRequestActive = true;
3247 if (true == mOdcpiTimer.isActive()) {
3248 mOdcpiTimer.restart();
3249 } else {
3250 mOdcpiTimer.start();
3251 }
3252 // if ODCPI request is not active but the timer is active, then
3253 // just update the active state and wait for timer to expire
3254 // before requesting new ODCPI to avoid spamming ODCPI requests
3255 } else if (false == mOdcpiRequestActive && true == mOdcpiTimer.isActive()) {
3256 mOdcpiRequestActive = true;
3257 }
3258 mOdcpiRequest = request;
3259 // the request is being stopped, but allow timer to expire first
3260 // before stopping the timer just in case more ODCPI requests come
3261 // to avoid spamming more odcpi requests to the framework
3262 } else {
3263 mOdcpiRequestActive = false;
3264 }
3265 } else {
3266 LOC_LOGw("ODCPI request not supported");
3267 }
3268 }
3269
initOdcpiCommand(const OdcpiRequestCallback & callback)3270 void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback)
3271 {
3272 struct MsgInitOdcpi : public LocMsg {
3273 GnssAdapter& mAdapter;
3274 OdcpiRequestCallback mOdcpiCb;
3275 inline MsgInitOdcpi(GnssAdapter& adapter,
3276 const OdcpiRequestCallback& callback) :
3277 LocMsg(),
3278 mAdapter(adapter),
3279 mOdcpiCb(callback) {}
3280 inline virtual void proc() const {
3281 mAdapter.initOdcpi(mOdcpiCb);
3282 }
3283 };
3284
3285 sendMsg(new MsgInitOdcpi(*this, callback));
3286 }
3287
initOdcpi(const OdcpiRequestCallback & callback)3288 void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback)
3289 {
3290 mOdcpiRequestCb = callback;
3291
3292 /* Register for WIFI request */
3293 updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI,
3294 LOC_REGISTRATION_MASK_ENABLED);
3295 }
3296
injectOdcpiCommand(const Location & location)3297 void GnssAdapter::injectOdcpiCommand(const Location& location)
3298 {
3299 struct MsgInjectOdcpi : public LocMsg {
3300 GnssAdapter& mAdapter;
3301 Location mLocation;
3302 inline MsgInjectOdcpi(GnssAdapter& adapter, const Location& location) :
3303 LocMsg(),
3304 mAdapter(adapter),
3305 mLocation(location) {}
3306 inline virtual void proc() const {
3307 mAdapter.injectOdcpi(mLocation);
3308 }
3309 };
3310
3311 sendMsg(new MsgInjectOdcpi(*this, location));
3312 }
3313
injectOdcpi(const Location & location)3314 void GnssAdapter::injectOdcpi(const Location& location)
3315 {
3316 LOC_LOGd("ODCPI Injection: requestActive: %d timerActive: %d"
3317 "lat %.7f long %.7f",
3318 mOdcpiRequestActive, mOdcpiTimer.isActive(),
3319 location.latitude, location.longitude);
3320
3321 loc_api_adapter_err err = mLocApi->injectPosition(location);
3322 if (LOC_API_ADAPTER_ERR_SUCCESS != err) {
3323 LOC_LOGe("Inject Position API error %d", err);
3324 }
3325 }
3326
3327 // Called in the context of LocTimer thread
timeOutCallback()3328 void OdcpiTimer::timeOutCallback()
3329 {
3330 if (nullptr != mAdapter) {
3331 mAdapter->odcpiTimerExpireEvent();
3332 }
3333 }
3334
3335 // Called in the context of LocTimer thread
odcpiTimerExpireEvent()3336 void GnssAdapter::odcpiTimerExpireEvent()
3337 {
3338 struct MsgOdcpiTimerExpire : public LocMsg {
3339 GnssAdapter& mAdapter;
3340 inline MsgOdcpiTimerExpire(GnssAdapter& adapter) :
3341 LocMsg(),
3342 mAdapter(adapter) {}
3343 inline virtual void proc() const {
3344 mAdapter.odcpiTimerExpire();
3345 }
3346 };
3347 sendMsg(new MsgOdcpiTimerExpire(*this));
3348 }
odcpiTimerExpire()3349 void GnssAdapter::odcpiTimerExpire()
3350 {
3351 LOC_LOGd("requestActive: %d timerActive: %d",
3352 mOdcpiRequestActive, mOdcpiTimer.isActive());
3353
3354 // if ODCPI request is still active after timer
3355 // expires, request again and restart timer
3356 if (mOdcpiRequestActive) {
3357 mOdcpiRequestCb(mOdcpiRequest);
3358 mOdcpiTimer.restart();
3359 } else {
3360 mOdcpiTimer.stop();
3361 }
3362 }
3363
initDefaultAgps()3364 void GnssAdapter::initDefaultAgps() {
3365 LOC_LOGD("%s]: ", __func__);
3366
3367 void *handle = nullptr;
3368 if ((handle = dlopen("libloc_net_iface.so", RTLD_NOW)) == nullptr) {
3369 LOC_LOGD("%s]: libloc_net_iface.so not found !", __func__);
3370 return;
3371 }
3372
3373 LocAgpsGetAgpsCbInfo getAgpsCbInfo = (LocAgpsGetAgpsCbInfo)
3374 dlsym(handle, "LocNetIfaceAgps_getAgpsCbInfo");
3375 if (getAgpsCbInfo == nullptr) {
3376 LOC_LOGE("%s]: Failed to get method LocNetIfaceAgps_getStatusCb", __func__);
3377 return;
3378 }
3379
3380 AgpsCbInfo& cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this);
3381
3382 if (cbInfo.statusV4Cb == nullptr) {
3383 LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__);
3384 return;
3385 }
3386
3387 initAgps(cbInfo);
3388 }
3389
initDefaultAgpsCommand()3390 void GnssAdapter::initDefaultAgpsCommand() {
3391 LOC_LOGD("%s]: ", __func__);
3392
3393 struct MsgInitDefaultAgps : public LocMsg {
3394 GnssAdapter& mAdapter;
3395 inline MsgInitDefaultAgps(GnssAdapter& adapter) :
3396 LocMsg(),
3397 mAdapter(adapter) {
3398 }
3399 inline virtual void proc() const {
3400 mAdapter.initDefaultAgps();
3401 }
3402 };
3403
3404 sendMsg(new MsgInitDefaultAgps(*this));
3405 }
3406
3407 /* INIT LOC AGPS MANAGER */
3408
initAgps(const AgpsCbInfo & cbInfo)3409 void GnssAdapter::initAgps(const AgpsCbInfo& cbInfo) {
3410 LOC_LOGD("%s]: mAgpsCbInfo.cbPriority - %d; cbInfo.cbPriority - %d",
3411 __func__, mAgpsCbInfo.cbPriority, cbInfo.cbPriority)
3412
3413 if (!((ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB) ||
3414 (ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA))) {
3415 return;
3416 }
3417
3418 if (mAgpsCbInfo.cbPriority > cbInfo.cbPriority) {
3419 return;
3420 } else {
3421 mAgpsCbInfo = cbInfo;
3422
3423 mAgpsManager.registerFrameworkStatusCallback((AgnssStatusIpV4Cb)cbInfo.statusV4Cb);
3424
3425 mAgpsManager.createAgpsStateMachines();
3426
3427 /* Register for AGPS event mask */
3428 updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
3429 LOC_REGISTRATION_MASK_ENABLED);
3430 }
3431 }
3432
initAgpsCommand(const AgpsCbInfo & cbInfo)3433 void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){
3434 LOC_LOGI("GnssAdapter::initAgpsCommand");
3435
3436 /* Message to initialize AGPS module */
3437 struct AgpsMsgInit: public LocMsg {
3438 const AgpsCbInfo mCbInfo;
3439 GnssAdapter& mAdapter;
3440
3441 inline AgpsMsgInit(const AgpsCbInfo& cbInfo,
3442 GnssAdapter& adapter) :
3443 LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
3444 LOC_LOGV("AgpsMsgInit");
3445 }
3446
3447 inline virtual void proc() const {
3448 LOC_LOGV("AgpsMsgInit::proc()");
3449 mAdapter.initAgps(mCbInfo);
3450 }
3451 };
3452
3453 /* Send message to initialize AGPS Manager */
3454 sendMsg(new AgpsMsgInit(cbInfo, *this));
3455 }
3456
3457 /* GnssAdapter::requestATL
3458 * Method triggered in QMI thread as part of handling below message:
3459 * eQMI_LOC_SERVER_REQUEST_OPEN_V02
3460 * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
3461 * eQMI_LOC_WWAN_TYPE_INTERNET_V02
3462 * eQMI_LOC_WWAN_TYPE_AGNSS_V02 */
requestATL(int connHandle,LocAGpsType agpsType,LocApnTypeMask mask)3463 bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType, LocApnTypeMask mask){
3464
3465 LOC_LOGI("GnssAdapter::requestATL");
3466
3467 sendMsg( new AgpsMsgRequestATL(
3468 &mAgpsManager, connHandle, (AGpsExtType)agpsType, mask));
3469
3470 return true;
3471 }
3472
3473 /* GnssAdapter::requestSuplES
3474 * Method triggered in QMI thread as part of handling below message:
3475 * eQMI_LOC_SERVER_REQUEST_OPEN_V02
3476 * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
3477 * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
requestSuplES(int connHandle,LocApnTypeMask mask)3478 bool GnssAdapter::requestSuplES(int connHandle, LocApnTypeMask mask){
3479
3480 LOC_LOGI("GnssAdapter::requestSuplES");
3481
3482 sendMsg( new AgpsMsgRequestATL(
3483 &mAgpsManager, connHandle, LOC_AGPS_TYPE_SUPL_ES, mask));
3484
3485 return true;
3486 }
3487
3488 /* GnssAdapter::releaseATL
3489 * Method triggered in QMI thread as part of handling below message:
3490 * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
3491 * Triggers teardown of an existing AGPS call */
releaseATL(int connHandle)3492 bool GnssAdapter::releaseATL(int connHandle){
3493
3494 LOC_LOGI("GnssAdapter::releaseATL");
3495
3496 /* Release SUPL/INTERNET/SUPL_ES ATL */
3497 struct AgpsMsgReleaseATL: public LocMsg {
3498
3499 AgpsManager* mAgpsManager;
3500 int mConnHandle;
3501
3502 inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
3503 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
3504
3505 LOC_LOGV("AgpsMsgReleaseATL");
3506 }
3507
3508 inline virtual void proc() const {
3509
3510 LOC_LOGV("AgpsMsgReleaseATL::proc()");
3511 mAgpsManager->releaseATL(mConnHandle);
3512 }
3513 };
3514
3515 sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
3516
3517 return true;
3518 }
3519
3520 /* GnssAdapter::reportDataCallOpened
3521 * DS Client data call opened successfully.
3522 * Send message to AGPS Manager to handle. */
reportDataCallOpened()3523 bool GnssAdapter::reportDataCallOpened(){
3524
3525 LOC_LOGI("GnssAdapter::reportDataCallOpened");
3526
3527 struct AgpsMsgSuplEsOpened: public LocMsg {
3528
3529 AgpsManager* mAgpsManager;
3530
3531 inline AgpsMsgSuplEsOpened(AgpsManager* agpsManager) :
3532 LocMsg(), mAgpsManager(agpsManager) {
3533
3534 LOC_LOGV("AgpsMsgSuplEsOpened");
3535 }
3536
3537 inline virtual void proc() const {
3538
3539 LOC_LOGV("AgpsMsgSuplEsOpened::proc()");
3540 mAgpsManager->reportDataCallOpened();
3541 }
3542 };
3543
3544 sendMsg( new AgpsMsgSuplEsOpened(&mAgpsManager));
3545
3546 return true;
3547 }
3548
3549 /* GnssAdapter::reportDataCallClosed
3550 * DS Client data call closed.
3551 * Send message to AGPS Manager to handle. */
reportDataCallClosed()3552 bool GnssAdapter::reportDataCallClosed(){
3553
3554 LOC_LOGI("GnssAdapter::reportDataCallClosed");
3555
3556 struct AgpsMsgSuplEsClosed: public LocMsg {
3557
3558 AgpsManager* mAgpsManager;
3559
3560 inline AgpsMsgSuplEsClosed(AgpsManager* agpsManager) :
3561 LocMsg(), mAgpsManager(agpsManager) {
3562
3563 LOC_LOGV("AgpsMsgSuplEsClosed");
3564 }
3565
3566 inline virtual void proc() const {
3567
3568 LOC_LOGV("AgpsMsgSuplEsClosed::proc()");
3569 mAgpsManager->reportDataCallClosed();
3570 }
3571 };
3572
3573 sendMsg( new AgpsMsgSuplEsClosed(&mAgpsManager));
3574
3575 return true;
3576 }
3577
dataConnOpenCommand(AGpsExtType agpsType,const char * apnName,int apnLen,AGpsBearerType bearerType)3578 void GnssAdapter::dataConnOpenCommand(
3579 AGpsExtType agpsType,
3580 const char* apnName, int apnLen, AGpsBearerType bearerType){
3581
3582 LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
3583
3584 struct AgpsMsgAtlOpenSuccess: public LocMsg {
3585
3586 AgpsManager* mAgpsManager;
3587 AGpsExtType mAgpsType;
3588 char* mApnName;
3589 int mApnLen;
3590 AGpsBearerType mBearerType;
3591
3592 inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
3593 const char* apnName, int apnLen, AGpsBearerType bearerType) :
3594 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
3595 new char[apnLen + 1]), mApnLen(apnLen), mBearerType(bearerType) {
3596
3597 LOC_LOGV("AgpsMsgAtlOpenSuccess");
3598 if (mApnName == nullptr) {
3599 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
3600 return;
3601 }
3602 memcpy(mApnName, apnName, apnLen);
3603 mApnName[apnLen] = 0;
3604 }
3605
3606 inline ~AgpsMsgAtlOpenSuccess() {
3607 delete[] mApnName;
3608 }
3609
3610 inline virtual void proc() const {
3611
3612 LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
3613 mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType);
3614 }
3615 };
3616
3617 sendMsg( new AgpsMsgAtlOpenSuccess(
3618 &mAgpsManager, agpsType, apnName, apnLen, bearerType));
3619 }
3620
dataConnClosedCommand(AGpsExtType agpsType)3621 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
3622
3623 LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
3624
3625 struct AgpsMsgAtlClosed: public LocMsg {
3626
3627 AgpsManager* mAgpsManager;
3628 AGpsExtType mAgpsType;
3629
3630 inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
3631 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
3632
3633 LOC_LOGV("AgpsMsgAtlClosed");
3634 }
3635
3636 inline virtual void proc() const {
3637
3638 LOC_LOGV("AgpsMsgAtlClosed::proc()");
3639 mAgpsManager->reportAtlClosed(mAgpsType);
3640 }
3641 };
3642
3643 sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
3644 }
3645
dataConnFailedCommand(AGpsExtType agpsType)3646 void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
3647
3648 LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
3649
3650 struct AgpsMsgAtlOpenFailed: public LocMsg {
3651
3652 AgpsManager* mAgpsManager;
3653 AGpsExtType mAgpsType;
3654
3655 inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
3656 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
3657
3658 LOC_LOGV("AgpsMsgAtlOpenFailed");
3659 }
3660
3661 inline virtual void proc() const {
3662
3663 LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
3664 mAgpsManager->reportAtlOpenFailed(mAgpsType);
3665 }
3666 };
3667
3668 sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
3669 }
3670
convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo> & out,const GnssSvType & in_constellation,const SystemStatusReports & in)3671 void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
3672 const GnssSvType& in_constellation,
3673 const SystemStatusReports& in)
3674 {
3675 uint64_t sv_mask = 0ULL;
3676 uint32_t svid_min = 0;
3677 uint32_t svid_num = 0;
3678 uint32_t svid_idx = 0;
3679
3680 uint64_t eph_health_good_mask = 0ULL;
3681 uint64_t eph_health_bad_mask = 0ULL;
3682 uint64_t server_perdiction_available_mask = 0ULL;
3683 float server_perdiction_age = 0.0f;
3684
3685 // set constellationi based parameters
3686 switch (in_constellation) {
3687 case GNSS_SV_TYPE_GPS:
3688 svid_min = GNSS_BUGREPORT_GPS_MIN;
3689 svid_num = GPS_NUM;
3690 svid_idx = 0;
3691 if (!in.mSvHealth.empty()) {
3692 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
3693 eph_health_bad_mask = in.mSvHealth.back().mGpsBadMask;
3694 }
3695 if (!in.mXtra.empty()) {
3696 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
3697 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
3698 }
3699 break;
3700 case GNSS_SV_TYPE_GLONASS:
3701 svid_min = GNSS_BUGREPORT_GLO_MIN;
3702 svid_num = GLO_NUM;
3703 svid_idx = GPS_NUM;
3704 if (!in.mSvHealth.empty()) {
3705 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
3706 eph_health_bad_mask = in.mSvHealth.back().mGloBadMask;
3707 }
3708 if (!in.mXtra.empty()) {
3709 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
3710 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
3711 }
3712 break;
3713 case GNSS_SV_TYPE_QZSS:
3714 svid_min = GNSS_BUGREPORT_QZSS_MIN;
3715 svid_num = QZSS_NUM;
3716 svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
3717 if (!in.mSvHealth.empty()) {
3718 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
3719 eph_health_bad_mask = in.mSvHealth.back().mQzssBadMask;
3720 }
3721 if (!in.mXtra.empty()) {
3722 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
3723 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
3724 }
3725 break;
3726 case GNSS_SV_TYPE_BEIDOU:
3727 svid_min = GNSS_BUGREPORT_BDS_MIN;
3728 svid_num = BDS_NUM;
3729 svid_idx = GPS_NUM+GLO_NUM;
3730 if (!in.mSvHealth.empty()) {
3731 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
3732 eph_health_bad_mask = in.mSvHealth.back().mBdsBadMask;
3733 }
3734 if (!in.mXtra.empty()) {
3735 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
3736 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
3737 }
3738 break;
3739 case GNSS_SV_TYPE_GALILEO:
3740 svid_min = GNSS_BUGREPORT_GAL_MIN;
3741 svid_num = GAL_NUM;
3742 svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
3743 if (!in.mSvHealth.empty()) {
3744 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
3745 eph_health_bad_mask = in.mSvHealth.back().mGalBadMask;
3746 }
3747 if (!in.mXtra.empty()) {
3748 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
3749 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
3750 }
3751 break;
3752 default:
3753 return;
3754 }
3755
3756 // extract each sv info from systemstatus report
3757 for(uint32_t i=0; i<svid_num && (svid_idx+i)<SV_ALL_NUM; i++) {
3758
3759 GnssDebugSatelliteInfo s = {};
3760 s.size = sizeof(s);
3761 s.svid = i + svid_min;
3762 s.constellation = in_constellation;
3763
3764 if (!in.mNavData.empty()) {
3765 s.mEphemerisType = in.mNavData.back().mNav[svid_idx+i].mType;
3766 s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
3767 }
3768 else {
3769 s.mEphemerisType = GNSS_EPH_TYPE_UNKNOWN;
3770 s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
3771 }
3772
3773 sv_mask = 0x1ULL << i;
3774 if (eph_health_good_mask & sv_mask) {
3775 s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
3776 }
3777 else if (eph_health_bad_mask & sv_mask) {
3778 s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
3779 }
3780 else {
3781 s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
3782 }
3783
3784 if (!in.mNavData.empty()) {
3785 s.ephemerisAgeSeconds =
3786 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
3787 }
3788 else {
3789 s.ephemerisAgeSeconds = 0.0f;
3790 }
3791
3792 if (server_perdiction_available_mask & sv_mask) {
3793 s.serverPredictionIsAvailable = true;
3794 }
3795 else {
3796 s.serverPredictionIsAvailable = false;
3797 }
3798
3799 s.serverPredictionAgeSeconds = server_perdiction_age;
3800 out.push_back(s);
3801 }
3802
3803 return;
3804 }
3805
getDebugReport(GnssDebugReport & r)3806 bool GnssAdapter::getDebugReport(GnssDebugReport& r)
3807 {
3808 LOC_LOGD("%s]: ", __func__);
3809
3810 SystemStatus* systemstatus = getSystemStatus();
3811 if (nullptr == systemstatus) {
3812 return false;
3813 }
3814
3815 SystemStatusReports reports = {};
3816 systemstatus->getReport(reports, true);
3817
3818 r.size = sizeof(r);
3819
3820 // location block
3821 r.mLocation.size = sizeof(r.mLocation);
3822 if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
3823 r.mLocation.mValid = true;
3824 r.mLocation.mLocation.latitude =
3825 reports.mLocation.back().mLocation.gpsLocation.latitude;
3826 r.mLocation.mLocation.longitude =
3827 reports.mLocation.back().mLocation.gpsLocation.longitude;
3828 r.mLocation.mLocation.altitude =
3829 reports.mLocation.back().mLocation.gpsLocation.altitude;
3830 r.mLocation.mLocation.speed =
3831 (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
3832 r.mLocation.mLocation.bearing =
3833 (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
3834 r.mLocation.mLocation.accuracy =
3835 (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
3836
3837 r.mLocation.verticalAccuracyMeters =
3838 reports.mLocation.back().mLocationEx.vert_unc;
3839 r.mLocation.speedAccuracyMetersPerSecond =
3840 reports.mLocation.back().mLocationEx.speed_unc;
3841 r.mLocation.bearingAccuracyDegrees =
3842 reports.mLocation.back().mLocationEx.bearing_unc;
3843
3844 r.mLocation.mUtcReported =
3845 reports.mLocation.back().mUtcReported;
3846 }
3847 else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
3848 r.mLocation.mValid = true;
3849 r.mLocation.mLocation.latitude =
3850 (double)(reports.mBestPosition.back().mBestLat) * RAD2DEG;
3851 r.mLocation.mLocation.longitude =
3852 (double)(reports.mBestPosition.back().mBestLon) * RAD2DEG;
3853 r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt;
3854 r.mLocation.mLocation.accuracy =
3855 (double)(reports.mBestPosition.back().mBestHepe);
3856
3857 r.mLocation.mUtcReported = reports.mBestPosition.back().mUtcReported;
3858 }
3859 else {
3860 r.mLocation.mValid = false;
3861 }
3862
3863 if (r.mLocation.mValid) {
3864 LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
3865 r.mLocation.mLocation.latitude,
3866 r.mLocation.mLocation.longitude,
3867 r.mLocation.mLocation.altitude,
3868 r.mLocation.mLocation.speed);
3869 }
3870
3871 // time block
3872 r.mTime.size = sizeof(r.mTime);
3873 if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
3874 r.mTime.mValid = true;
3875 r.mTime.timeEstimate =
3876 (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
3877 GNSS_UTC_TIME_OFFSET)*24*60*60 -
3878 (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
3879 (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
3880
3881 if (reports.mTimeAndClock.back().mTimeUncNs > 0) {
3882 // TimeUncNs value is available
3883 r.mTime.timeUncertaintyNs =
3884 (float)(reports.mTimeAndClock.back().mLeapSecUnc)*1000.0f +
3885 (float)(reports.mTimeAndClock.back().mTimeUncNs);
3886 } else {
3887 // fall back to legacy TimeUnc
3888 r.mTime.timeUncertaintyNs =
3889 ((float)(reports.mTimeAndClock.back().mTimeUnc) +
3890 (float)(reports.mTimeAndClock.back().mLeapSecUnc))*1000.0f;
3891 }
3892
3893 r.mTime.frequencyUncertaintyNsPerSec =
3894 (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
3895 LOC_LOGV("getDebugReport - timeestimate=%" PRIu64 " unc=%f frequnc=%f",
3896 r.mTime.timeEstimate,
3897 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
3898 }
3899 else {
3900 r.mTime.mValid = false;
3901 }
3902
3903 // satellite info block
3904 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
3905 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
3906 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
3907 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
3908 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
3909 LOC_LOGV("getDebugReport - satellite=%zu", r.mSatelliteInfo.size());
3910
3911 return true;
3912 }
3913
3914 /* get AGC information from system status and fill it */
3915 void
getAgcInformation(GnssMeasurementsNotification & measurements,int msInWeek)3916 GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek)
3917 {
3918 SystemStatus* systemstatus = getSystemStatus();
3919
3920 if (nullptr != systemstatus) {
3921 SystemStatusReports reports = {};
3922 systemstatus->getReport(reports, true);
3923
3924 if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
3925 (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
3926
3927 for (size_t i = 0; i < measurements.count; i++) {
3928 switch (measurements.measurements[i].svType) {
3929 case GNSS_SV_TYPE_GPS:
3930 case GNSS_SV_TYPE_QZSS:
3931 measurements.measurements[i].agcLevelDb =
3932 reports.mRfAndParams.back().mAgcGps;
3933 measurements.measurements[i].flags |=
3934 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
3935 break;
3936
3937 case GNSS_SV_TYPE_GALILEO:
3938 measurements.measurements[i].agcLevelDb =
3939 reports.mRfAndParams.back().mAgcGal;
3940 measurements.measurements[i].flags |=
3941 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
3942 break;
3943
3944 case GNSS_SV_TYPE_GLONASS:
3945 measurements.measurements[i].agcLevelDb =
3946 reports.mRfAndParams.back().mAgcGlo;
3947 measurements.measurements[i].flags |=
3948 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
3949 break;
3950
3951 case GNSS_SV_TYPE_BEIDOU:
3952 measurements.measurements[i].agcLevelDb =
3953 reports.mRfAndParams.back().mAgcBds;
3954 measurements.measurements[i].flags |=
3955 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
3956 break;
3957
3958 case GNSS_SV_TYPE_SBAS:
3959 case GNSS_SV_TYPE_UNKNOWN:
3960 default:
3961 break;
3962 }
3963 }
3964 }
3965 }
3966 }
3967
3968 /* Callbacks registered with loc_net_iface library */
agpsOpenResultCb(bool isSuccess,AGpsExtType agpsType,const char * apn,AGpsBearerType bearerType,void * userDataPtr)3969 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
3970 AGpsBearerType bearerType, void* userDataPtr) {
3971 LOC_LOGD("%s]: ", __func__);
3972 if (userDataPtr == nullptr) {
3973 LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
3974 return;
3975 }
3976 if (apn == nullptr) {
3977 LOC_LOGE("%s]: apn is nullptr.", __func__);
3978 return;
3979 }
3980 GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
3981 if (isSuccess) {
3982 adapter->dataConnOpenCommand(agpsType, apn, strlen(apn), bearerType);
3983 } else {
3984 adapter->dataConnFailedCommand(agpsType);
3985 }
3986 }
3987
agpsCloseResultCb(bool isSuccess,AGpsExtType agpsType,void * userDataPtr)3988 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr) {
3989 LOC_LOGD("%s]: ", __func__);
3990 if (userDataPtr == nullptr) {
3991 LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
3992 return;
3993 }
3994 GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
3995 if (isSuccess) {
3996 adapter->dataConnClosedCommand(agpsType);
3997 } else {
3998 adapter->dataConnFailedCommand(agpsType);
3999 }
4000 }
4001