1 /* Copyright (c) 2017-2021 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 <sstream>
44 #include <loc_log.h>
45 #include <loc_nmea.h>
46 #include <Agps.h>
47 #include <SystemStatus.h>
48 #include <vector>
49 #include <loc_misc_utils.h>
50
51 #define RAD2DEG (180.0 / M_PI)
52 #define PROCESS_NAME_ENGINE_SERVICE "engine-service"
53 #define MIN_TRACKING_INTERVAL (100) // 100 msec
54
55 #define BILLION_NSEC (1000000000ULL)
56 #define NMEA_MIN_THRESHOLD_MSEC (99)
57 #define NMEA_MAX_THRESHOLD_MSEC (975)
58
59 using namespace loc_core;
60
61 /* Method to fetch status cb from loc_net_iface library */
62 typedef AgpsCbInfo& (*LocAgpsGetAgpsCbInfo)(LocAgpsOpenResultCb openResultCb,
63 LocAgpsCloseResultCb closeResultCb, void* userDataPtr);
64
65 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
66 AGpsBearerType bearerType, void* userDataPtr);
67 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr);
68
69 typedef const CdfwInterface* (*getCdfwInterface)();
70
GnssAdapter()71 GnssAdapter::GnssAdapter() :
72 LocAdapterBase(0,
73 LocContext::getLocContext(NULL,
74 NULL,
75 LocContext::mLocationHalName,
76 false),
77 true, nullptr, true),
78 mEngHubProxy(new EngineHubProxyBase()),
79 mQDgnssListenerHDL(nullptr),
80 mCdfwInterface(nullptr),
81 mDGnssNeedReport(false),
82 mDGnssDataUsage(false),
83 mLocPositionMode(),
84 mNHzNeeded(false),
85 mSPEAlreadyRunningAtHighestInterval(false),
86 mGnssSvIdUsedInPosition(),
87 mGnssSvIdUsedInPosAvail(false),
88 mControlCallbacks(),
89 mAfwControlId(0),
90 mNmeaMask(0),
91 mGnssSvIdConfig(),
92 mGnssSvTypeConfig(),
93 mGnssSvTypeConfigCb(nullptr),
94 mLocConfigInfo{},
95 mNiData(),
96 mAgpsManager(),
97 mOdcpiRequestCb(nullptr),
98 mOdcpiRequestActive(false),
99 mOdcpiTimer(this),
100 mOdcpiRequest(),
101 mSystemStatus(SystemStatus::getInstance(mMsgTask)),
102 mServerUrl(":"),
103 mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask),
104 mLocSystemInfo{},
105 mBlockCPIInfo{},
106 mNfwCb(NULL),
107 mPowerOn(false),
108 mAllowFlpNetworkFixes(0),
109 mGnssEnergyConsumedCb(nullptr),
110 mPowerStateCb(nullptr),
111 mIsE911Session(NULL),
112 mGnssMbSvIdUsedInPosition{},
113 mGnssMbSvIdUsedInPosAvail(false),
114 mSupportNfwControl(true),
115 mSystemPowerState(POWER_STATE_UNKNOWN),
116 mIsMeasCorrInterfaceOpen(false),
117 mIsAntennaInfoInterfaceOpened(false)
118 {
119 LOC_LOGD("%s]: Constructor %p", __func__, this);
120 mLocPositionMode.mode = LOC_POSITION_MODE_INVALID;
121
122 pthread_condattr_t condAttr;
123 pthread_condattr_init(&condAttr);
124 pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
125 pthread_cond_init(&mNiData.session.tCond, &condAttr);
126 pthread_cond_init(&mNiData.sessionEs.tCond, &condAttr);
127 pthread_condattr_destroy(&condAttr);
128
129 /* Set ATL open/close callbacks */
130 AgpsAtlOpenStatusCb atlOpenStatusCb =
131 [this](int handle, int isSuccess, char* apn, uint32_t apnLen,
__anon36c2e9730102(int handle, int isSuccess, char* apn, uint32_t apnLen, AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) 132 AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) {
133
134 mLocApi->atlOpenStatus(
135 handle, isSuccess, apn, apnLen, bearerType, agpsType, mask);
136 };
137 AgpsAtlCloseStatusCb atlCloseStatusCb =
__anon36c2e9730202(int handle, int isSuccess) 138 [this](int handle, int isSuccess) {
139
140 mLocApi->atlCloseStatus(handle, isSuccess);
141 };
142 mAgpsManager.registerATLCallbacks(atlOpenStatusCb, atlCloseStatusCb);
143
144 readConfigCommand();
145 initDefaultAgpsCommand();
146 initEngHubProxyCommand();
147 initDGnssUsableReporter();
148
149 // at last step, let us inform adapater base that we are done
150 // with initialization, e.g.: ready to process handleEngineUpEvent
151 doneInit();
152 }
153
154 void
setControlCallbacksCommand(LocationControlCallbacks & controlCallbacks)155 GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
156 {
157 struct MsgSetControlCallbacks : public LocMsg {
158 GnssAdapter& mAdapter;
159 const LocationControlCallbacks mControlCallbacks;
160 inline MsgSetControlCallbacks(GnssAdapter& adapter,
161 LocationControlCallbacks& controlCallbacks) :
162 LocMsg(),
163 mAdapter(adapter),
164 mControlCallbacks(controlCallbacks) {}
165 inline virtual void proc() const {
166 mAdapter.setControlCallbacks(mControlCallbacks);
167 }
168 };
169
170 sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
171 }
172
173 void
convertOptions(LocPosMode & out,const TrackingOptions & trackingOptions)174 GnssAdapter::convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions)
175 {
176 switch (trackingOptions.mode) {
177 case GNSS_SUPL_MODE_MSB:
178 out.mode = LOC_POSITION_MODE_MS_BASED;
179 break;
180 case GNSS_SUPL_MODE_MSA:
181 out.mode = LOC_POSITION_MODE_MS_ASSISTED;
182 break;
183 default:
184 out.mode = LOC_POSITION_MODE_STANDALONE;
185 break;
186 }
187 out.share_position = true;
188 out.min_interval = trackingOptions.minInterval;
189 out.powerMode = trackingOptions.powerMode;
190 out.timeBetweenMeasurements = trackingOptions.tbm;
191 }
192
193 bool
checkAndSetSPEToRunforNHz(TrackingOptions & out)194 GnssAdapter::checkAndSetSPEToRunforNHz(TrackingOptions & out) {
195
196 // first check if NHz meas is needed at all, if not, just return false
197 // if a NHz capable engine is subscribed for NHz measurement or NHz positions,
198 // always run the SPE only session at 100ms TBF.
199 // If SPE session is already set to highest interval, no need to start it again.
200
201 bool isSPERunningAtHighestInterval = false;
202
203 if (!mNHzNeeded) {
204 LOC_LOGd("No nHz session needed.");
205 } else if (mSPEAlreadyRunningAtHighestInterval) {
206 LOC_LOGd("SPE is already running at highest interval.");
207 isSPERunningAtHighestInterval = true;
208 } else if (out.minInterval > MIN_TRACKING_INTERVAL) {
209 out.minInterval = MIN_TRACKING_INTERVAL;
210 LOC_LOGd("nHz session is needed, starting SPE only session at 100ms TBF.");
211 mSPEAlreadyRunningAtHighestInterval = true;
212 }
213
214 return isSPERunningAtHighestInterval;
215 }
216
217
218 void
convertLocation(Location & out,const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,const LocPosTechMask techMask)219 GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation,
220 const GpsLocationExtended& locationExtended,
221 const LocPosTechMask techMask)
222 {
223 memset(&out, 0, sizeof(Location));
224 out.size = sizeof(Location);
225 if (LOC_GPS_LOCATION_HAS_LAT_LONG & ulpLocation.gpsLocation.flags) {
226 out.flags |= LOCATION_HAS_LAT_LONG_BIT;
227 out.latitude = ulpLocation.gpsLocation.latitude;
228 out.longitude = ulpLocation.gpsLocation.longitude;
229 }
230 if (LOC_GPS_LOCATION_HAS_ALTITUDE & ulpLocation.gpsLocation.flags) {
231 out.flags |= LOCATION_HAS_ALTITUDE_BIT;
232 out.altitude = ulpLocation.gpsLocation.altitude;
233 }
234 if (LOC_GPS_LOCATION_HAS_SPEED & ulpLocation.gpsLocation.flags) {
235 out.flags |= LOCATION_HAS_SPEED_BIT;
236 out.speed = ulpLocation.gpsLocation.speed;
237 }
238 if (LOC_GPS_LOCATION_HAS_BEARING & ulpLocation.gpsLocation.flags) {
239 out.flags |= LOCATION_HAS_BEARING_BIT;
240 out.bearing = ulpLocation.gpsLocation.bearing;
241 }
242 if (LOC_GPS_LOCATION_HAS_ACCURACY & ulpLocation.gpsLocation.flags) {
243 out.flags |= LOCATION_HAS_ACCURACY_BIT;
244 out.accuracy = ulpLocation.gpsLocation.accuracy;
245 }
246 if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
247 out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
248 out.verticalAccuracy = locationExtended.vert_unc;
249 }
250 if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
251 out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
252 out.speedAccuracy = locationExtended.speed_unc;
253 }
254 if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
255 out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
256 out.bearingAccuracy = locationExtended.bearing_unc;
257 }
258 out.timestamp = ulpLocation.gpsLocation.timestamp;
259 if (LOC_POS_TECH_MASK_SATELLITE & techMask) {
260 out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
261 }
262 if (LOC_POS_TECH_MASK_CELLID & techMask) {
263 out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
264 }
265 if (LOC_POS_TECH_MASK_WIFI & techMask) {
266 out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
267 }
268 if (LOC_POS_TECH_MASK_SENSORS & techMask) {
269 out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
270 }
271
272 if (LOC_GPS_LOCATION_HAS_SPOOF_MASK & ulpLocation.gpsLocation.flags) {
273 out.flags |= LOCATION_HAS_SPOOF_MASK;
274 out.spoofMask = ulpLocation.gpsLocation.spoof_mask;
275 }
276 if (LOC_GPS_LOCATION_HAS_ELAPSED_REAL_TIME & ulpLocation.gpsLocation.flags) {
277 out.flags |= LOCATION_HAS_ELAPSED_REAL_TIME;
278 out.elapsedRealTime = ulpLocation.gpsLocation.elapsedRealTime;
279 out.elapsedRealTimeUnc = ulpLocation.gpsLocation.elapsedRealTimeUnc;
280 }
281 }
282
283 /* This is utility routine that computes number of SV used
284 in the fix from the svUsedIdsMask.
285 */
286 #define MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION 64
getNumSvUsed(uint64_t svUsedIdsMask,int totalSvCntInThisConstellation)287 uint16_t GnssAdapter::getNumSvUsed(uint64_t svUsedIdsMask,
288 int totalSvCntInThisConstellation)
289 {
290 if (totalSvCntInThisConstellation > MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION) {
291 LOC_LOGe ("error: total SV count in this constellation %d exceeded limit of %d",
292 totalSvCntInThisConstellation, MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION);
293 return 0;
294 }
295
296 uint16_t numSvUsed = 0;
297 uint64_t mask = 0x1;
298 for (int i = 0; i < totalSvCntInThisConstellation; i++) {
299 if (svUsedIdsMask & mask) {
300 numSvUsed++;
301 }
302 mask <<= 1;
303 }
304
305 return numSvUsed;
306 }
307
308 void
convertLocationInfo(GnssLocationInfoNotification & out,const GpsLocationExtended & locationExtended)309 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
310 const GpsLocationExtended& locationExtended)
311 {
312 out.size = sizeof(GnssLocationInfoNotification);
313 if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
314 out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
315 out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
316 }
317 if (GPS_LOCATION_EXTENDED_HAS_EXT_DOP & locationExtended.flags) {
318 out.flags |= (GNSS_LOCATION_INFO_DOP_BIT|GNSS_LOCATION_INFO_EXT_DOP_BIT);
319 out.pdop = locationExtended.extDOP.PDOP;
320 out.hdop = locationExtended.extDOP.HDOP;
321 out.vdop = locationExtended.extDOP.VDOP;
322 out.gdop = locationExtended.extDOP.GDOP;
323 out.tdop = locationExtended.extDOP.TDOP;
324 } else if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
325 out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
326 out.pdop = locationExtended.pdop;
327 out.hdop = locationExtended.hdop;
328 out.vdop = locationExtended.vdop;
329 }
330 if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
331 out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
332 out.magneticDeviation = locationExtended.magneticDeviation;
333 }
334 if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
335 out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
336 switch (locationExtended.horizontal_reliability) {
337 case LOC_RELIABILITY_VERY_LOW:
338 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
339 break;
340 case LOC_RELIABILITY_LOW:
341 out.horReliability = LOCATION_RELIABILITY_LOW;
342 break;
343 case LOC_RELIABILITY_MEDIUM:
344 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
345 break;
346 case LOC_RELIABILITY_HIGH:
347 out.horReliability = LOCATION_RELIABILITY_HIGH;
348 break;
349 default:
350 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
351 break;
352 }
353 }
354 if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
355 out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
356 switch (locationExtended.vertical_reliability) {
357 case LOC_RELIABILITY_VERY_LOW:
358 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
359 break;
360 case LOC_RELIABILITY_LOW:
361 out.verReliability = LOCATION_RELIABILITY_LOW;
362 break;
363 case LOC_RELIABILITY_MEDIUM:
364 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
365 break;
366 case LOC_RELIABILITY_HIGH:
367 out.verReliability = LOCATION_RELIABILITY_HIGH;
368 break;
369 default:
370 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
371 break;
372 }
373 }
374 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
375 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
376 out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
377 }
378 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
379 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
380 out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
381 }
382 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
383 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
384 out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
385 }
386 if (GPS_LOCATION_EXTENDED_HAS_NORTH_STD_DEV & locationExtended.flags) {
387 out.flags |= GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT;
388 out.northStdDeviation = locationExtended.northStdDeviation;
389 }
390 if (GPS_LOCATION_EXTENDED_HAS_EAST_STD_DEV & locationExtended.flags) {
391 out.flags |= GNSS_LOCATION_INFO_EAST_STD_DEV_BIT;
392 out.eastStdDeviation = locationExtended.eastStdDeviation;
393 }
394 if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) {
395 out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_BIT;
396 out.northVelocity = locationExtended.northVelocity;
397 }
398 if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) {
399 out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT;
400 out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation;
401 }
402 if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) {
403 out.flags |= GNSS_LOCATION_INFO_EAST_VEL_BIT;
404 out.eastVelocity = locationExtended.eastVelocity;
405 }
406 if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) {
407 out.flags |= GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT;
408 out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation;
409 }
410 if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) {
411 out.flags |= GNSS_LOCATION_INFO_UP_VEL_BIT;
412 out.upVelocity = locationExtended.upVelocity;
413 }
414 if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) {
415 out.flags |= GNSS_LOCATION_INFO_UP_VEL_UNC_BIT;
416 out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation;
417 }
418 if (GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA & locationExtended.flags) {
419 out.flags |= GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT;
420 out.svUsedInPosition.gpsSvUsedIdsMask =
421 locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask;
422 out.svUsedInPosition.gloSvUsedIdsMask =
423 locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask;
424 out.svUsedInPosition.galSvUsedIdsMask =
425 locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask;
426 out.svUsedInPosition.bdsSvUsedIdsMask =
427 locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask;
428 out.svUsedInPosition.qzssSvUsedIdsMask =
429 locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask;
430 out.svUsedInPosition.navicSvUsedIdsMask =
431 locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask;
432
433 out.flags |= GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT;
434 out.numSvUsedInPosition = getNumSvUsed(out.svUsedInPosition.gpsSvUsedIdsMask,
435 GPS_SV_PRN_MAX - GPS_SV_PRN_MIN + 1);
436 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.gloSvUsedIdsMask,
437 GLO_SV_PRN_MAX - GLO_SV_PRN_MIN + 1);
438 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.qzssSvUsedIdsMask,
439 QZSS_SV_PRN_MAX - QZSS_SV_PRN_MIN + 1);
440 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.bdsSvUsedIdsMask,
441 BDS_SV_PRN_MAX - BDS_SV_PRN_MIN + 1);
442 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.galSvUsedIdsMask,
443 GAL_SV_PRN_MAX - GAL_SV_PRN_MIN + 1);
444 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.navicSvUsedIdsMask,
445 NAVIC_SV_PRN_MAX - NAVIC_SV_PRN_MIN + 1);
446
447 out.numOfMeasReceived = locationExtended.numOfMeasReceived;
448 for (int idx =0; idx < locationExtended.numOfMeasReceived; idx++) {
449 out.measUsageInfo[idx].gnssSignalType =
450 locationExtended.measUsageInfo[idx].gnssSignalType;
451 out.measUsageInfo[idx].gnssSvId =
452 locationExtended.measUsageInfo[idx].gnssSvId;
453 out.measUsageInfo[idx].gnssConstellation =
454 locationExtended.measUsageInfo[idx].gnssConstellation;
455 }
456 }
457 if (GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK & locationExtended.flags) {
458 out.flags |= GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT;
459 out.navSolutionMask = locationExtended.navSolutionMask;
460 }
461 if (GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK & locationExtended.flags) {
462 out.flags |= GNSS_LOCATION_INFO_POS_TECH_MASK_BIT;
463 out.posTechMask = locationExtended.tech_mask;
464 }
465 if (GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA & locationExtended.flags) {
466 out.flags |= GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA;
467 if (locationExtended.bodyFrameData.bodyFrameDataMask &
468 LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT) {
469 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT;
470 }
471 if (locationExtended.bodyFrameData.bodyFrameDataMask &
472 LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT) {
473 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT;
474 }
475 if (locationExtended.bodyFrameData.bodyFrameDataMask &
476 LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT) {
477 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT;
478 }
479 if (locationExtended.bodyFrameData.bodyFrameDataMask &
480 LOCATION_NAV_DATA_HAS_YAW_RATE_BIT) {
481 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_BIT;
482 }
483 if (locationExtended.bodyFrameData.bodyFrameDataMask &
484 LOCATION_NAV_DATA_HAS_PITCH_BIT) {
485 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_BIT;
486 }
487
488 if (locationExtended.bodyFrameData.bodyFrameDataMask &
489 LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT) {
490 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT;
491 }
492 if (locationExtended.bodyFrameData.bodyFrameDataMask &
493 LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT) {
494 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT;
495 }
496 if (locationExtended.bodyFrameData.bodyFrameDataMask &
497 LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT) {
498 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT;
499 }
500 if (locationExtended.bodyFrameData.bodyFrameDataMask &
501 LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT) {
502 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT;
503 }
504 if (locationExtended.bodyFrameData.bodyFrameDataMask &
505 LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT) {
506 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT;
507 }
508
509 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
510 LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT) {
511 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT;
512 }
513 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
514 LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT) {
515 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT;
516 }
517 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
518 LOCATION_NAV_DATA_HAS_ROLL_BIT) {
519 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_BIT;
520 }
521 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
522 LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT) {
523 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT;
524 }
525 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
526 LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT) {
527 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT;
528 }
529 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
530 LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT) {
531 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT;
532 }
533 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
534 LOCATION_NAV_DATA_HAS_YAW_BIT) {
535 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_BIT;
536 }
537 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
538 LOCATION_NAV_DATA_HAS_YAW_UNC_BIT) {
539 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_UNC_BIT;
540 }
541
542 out.bodyFrameData.longAccel = locationExtended.bodyFrameData.longAccel;
543 out.bodyFrameData.latAccel = locationExtended.bodyFrameData.latAccel;
544 out.bodyFrameData.vertAccel = locationExtended.bodyFrameData.vertAccel;
545 out.bodyFrameData.yawRate = locationExtended.bodyFrameData.yawRate;
546 out.bodyFrameData.pitch = locationExtended.bodyFrameData.pitch;
547 out.bodyFrameData.longAccelUnc = locationExtended.bodyFrameData.longAccelUnc;
548 out.bodyFrameData.latAccelUnc = locationExtended.bodyFrameData.latAccelUnc;
549 out.bodyFrameData.vertAccelUnc = locationExtended.bodyFrameData.vertAccelUnc;
550 out.bodyFrameData.yawRateUnc = locationExtended.bodyFrameData.yawRateUnc;
551 out.bodyFrameData.pitchUnc = locationExtended.bodyFrameData.pitchUnc;
552
553 out.bodyFrameDataExt.pitchRate = locationExtended.bodyFrameDataExt.pitchRate;
554 out.bodyFrameDataExt.pitchRateUnc = locationExtended.bodyFrameDataExt.pitchRateUnc;
555 out.bodyFrameDataExt.roll = locationExtended.bodyFrameDataExt.roll;
556 out.bodyFrameDataExt.rollUnc = locationExtended.bodyFrameDataExt.rollUnc;
557 out.bodyFrameDataExt.rollRate = locationExtended.bodyFrameDataExt.rollRate;
558 out.bodyFrameDataExt.rollRateUnc = locationExtended.bodyFrameDataExt.rollRateUnc;
559 out.bodyFrameDataExt.yaw = locationExtended.bodyFrameDataExt.yaw;
560 out.bodyFrameDataExt.yawUnc = locationExtended.bodyFrameDataExt.yawUnc;
561 }
562 if (GPS_LOCATION_EXTENDED_HAS_GPS_TIME & locationExtended.flags) {
563 out.flags |= GPS_LOCATION_EXTENDED_HAS_GPS_TIME;
564 out.gnssSystemTime.gnssSystemTimeSrc = locationExtended.gnssSystemTime.gnssSystemTimeSrc;
565 out.gnssSystemTime.u = locationExtended.gnssSystemTime.u;
566 }
567 if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) {
568 out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL;
569 out.northVelocity = locationExtended.northVelocity;
570 }
571 if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) {
572 out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL;
573 out.eastVelocity = locationExtended.eastVelocity;
574 }
575 if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) {
576 out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL;
577 out.upVelocity = locationExtended.upVelocity;
578 }
579 if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) {
580 out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC;
581 out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation;
582 }
583 if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) {
584 out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC;
585 out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation;
586 }
587 if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) {
588 out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC;
589 out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation;
590 }
591
592 // Validity of this structure is established from the timeSrc of the GnssSystemTime structure.
593 out.gnssSystemTime = locationExtended.gnssSystemTime;
594
595 if (GPS_LOCATION_EXTENDED_HAS_LEAP_SECONDS & locationExtended.flags) {
596 out.flags |= GNSS_LOCATION_INFO_LEAP_SECONDS_BIT;
597 out.leapSeconds = locationExtended.leapSeconds;
598 }
599
600 if (GPS_LOCATION_EXTENDED_HAS_TIME_UNC & locationExtended.flags) {
601 out.flags |= GNSS_LOCATION_INFO_TIME_UNC_BIT;
602 out.timeUncMs = locationExtended.timeUncMs;
603 }
604
605 if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_CONFIDENCE & locationExtended.flags) {
606 out.flags |= GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT;
607 out.calibrationConfidence = locationExtended.calibrationConfidence;
608 }
609
610 if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_STATUS & locationExtended.flags) {
611 out.flags |= GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT;
612 out.calibrationStatus = locationExtended.calibrationStatus;
613 }
614
615 if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & locationExtended.flags) {
616 out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
617 out.locOutputEngType = locationExtended.locOutputEngType;
618 }
619
620 if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_MASK & locationExtended.flags) {
621 out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT;
622 out.locOutputEngMask = locationExtended.locOutputEngMask;
623 }
624
625 if (GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX & locationExtended.flags) {
626 out.flags |= GNSS_LOCATION_INFO_CONFORMITY_INDEX_BIT;
627 out.conformityIndex = locationExtended.conformityIndex;
628 }
629
630 if (GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED & locationExtended.flags) {
631 out.flags |= GNSS_LOCATION_INFO_LLA_VRP_BASED_BIT;
632 out.llaVRPBased = locationExtended.llaVRPBased;
633 }
634
635 if (GPS_LOCATION_EXTENDED_HAS_ENU_VELOCITY_LLA_VRP_BASED & locationExtended.flags) {
636 out.flags |= GNSS_LOCATION_INFO_ENU_VELOCITY_VRP_BASED_BIT;
637 // copy over east, north and up vrp based velocity
638 out.enuVelocityVRPBased[0] = locationExtended.enuVelocityVRPBased[0];
639 out.enuVelocityVRPBased[1] = locationExtended.enuVelocityVRPBased[1];
640 out.enuVelocityVRPBased[2] = locationExtended.enuVelocityVRPBased[2];
641 }
642 }
643
644
645
646 inline uint32_t
convertSuplVersion(const GnssConfigSuplVersion suplVersion)647 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
648 {
649 switch (suplVersion) {
650 case GNSS_CONFIG_SUPL_VERSION_2_0_4:
651 return 0x00020004;
652 case GNSS_CONFIG_SUPL_VERSION_2_0_0:
653 return 0x00020000;
654 case GNSS_CONFIG_SUPL_VERSION_2_0_2:
655 return 0x00020002;
656 case GNSS_CONFIG_SUPL_VERSION_1_0_0:
657 default:
658 return 0x00010000;
659 }
660 }
661
662 inline uint32_t
convertLppProfile(const GnssConfigLppProfile lppProfile)663 GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile)
664 {
665 switch (lppProfile) {
666 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE:
667 return 1;
668 case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE:
669 return 2;
670 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE:
671 return 3;
672 case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE:
673 default:
674 return 0;
675 }
676 }
677
678 uint32_t
convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)679 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
680 {
681 uint32_t mask = 0;
682 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
683 mask |= (1<<0);
684 }
685 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
686 mask |= (1<<1);
687 }
688 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
689 mask |= (1<<2);
690 }
691 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeControlPlaneMask) {
692 mask |= (1<<3);
693 }
694 return mask;
695 }
696
697 uint32_t
convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)698 GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
699 {
700 uint32_t mask = 0;
701 if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
702 mask |= (1<<0);
703 }
704 if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
705 mask |= (1<<1);
706 }
707 if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
708 mask |= (1<<2);
709 }
710 if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUserPlaneMask) {
711 mask |= (1<<3);
712 }
713 return mask;
714 }
715
716 uint32_t
convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)717 GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
718 {
719 uint32_t mask = 0;
720 if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
721 mask |= (1<<0);
722 }
723 if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
724 mask |= (1<<1);
725 }
726 if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
727 mask |= (1<<2);
728 }
729 if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
730 mask |= (1<<3);
731 }
732 return mask;
733 }
734
735 uint32_t
convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)736 GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
737 {
738 switch (emergencyPdnForEmergencySupl) {
739 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
740 return 1;
741 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
742 default:
743 return 0;
744 }
745 }
746
747 uint32_t
convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)748 GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
749 {
750 switch (suplEmergencyServices) {
751 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
752 return 1;
753 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
754 default:
755 return 0;
756 }
757 }
758
759 uint32_t
convertSuplMode(const GnssConfigSuplModeMask suplModeMask)760 GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
761 {
762 uint32_t mask = 0;
763 if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
764 mask |= (1<<0);
765 }
766 if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
767 mask |= (1<<1);
768 }
769 return mask;
770 }
771
772 void
readConfigCommand()773 GnssAdapter::readConfigCommand()
774 {
775 LOC_LOGD("%s]: ", __func__);
776
777 struct MsgReadConfig : public LocMsg {
778 GnssAdapter* mAdapter;
779 ContextBase& mContext;
780 inline MsgReadConfig(GnssAdapter* adapter,
781 ContextBase& context) :
782 LocMsg(),
783 mAdapter(adapter),
784 mContext(context) {}
785 inline virtual void proc() const {
786 static bool confReadDone = false;
787 if (!confReadDone) {
788 confReadDone = true;
789 // reads config into mContext->mGps_conf
790 mContext.readConfig();
791
792 uint32_t allowFlpNetworkFixes = 0;
793 static const loc_param_s_type flp_conf_param_table[] =
794 {
795 {"ALLOW_NETWORK_FIXES", &allowFlpNetworkFixes, NULL, 'n'},
796 };
797 UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table);
798 LOC_LOGd("allowFlpNetworkFixes %u", allowFlpNetworkFixes);
799 mAdapter->setAllowFlpNetworkFixes(allowFlpNetworkFixes);
800 }
801 }
802 };
803
804 if (mContext != NULL) {
805 sendMsg(new MsgReadConfig(this, *mContext));
806 }
807 }
808
809 void
setSuplHostServer(const char * server,int port,LocServerType type)810 GnssAdapter::setSuplHostServer(const char* server, int port, LocServerType type)
811 {
812 if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
813 char serverUrl[MAX_URL_LEN] = {};
814 int32_t length = -1;
815 const char noHost[] = "NONE";
816
817 if ((NULL == server) || (server[0] == 0) ||
818 (strncasecmp(noHost, server, sizeof(noHost)) == 0)) {
819 serverUrl[0] = '\0';
820 length = 0;
821 } else if (port > 0) {
822 length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", server, port);
823 }
824 if (LOC_AGPS_SUPL_SERVER != type && LOC_AGPS_MO_SUPL_SERVER != type) {
825 LOC_LOGe("Invalid type=%d", type);
826 } else if (length >= 0) {
827 if (LOC_AGPS_SUPL_SERVER == type) {
828 getServerUrl().assign(serverUrl);
829 strlcpy(ContextBase::mGps_conf.SUPL_HOST, server, LOC_MAX_PARAM_STRING);
830 ContextBase::mGps_conf.SUPL_PORT = port;
831 } else {
832 if (strncasecmp(getMoServerUrl().c_str(), serverUrl, sizeof(serverUrl)) != 0) {
833 getMoServerUrl().assign(serverUrl);
834 }
835 }
836 }
837 }
838 }
839
840 void
setConfig()841 GnssAdapter::setConfig()
842 {
843 LOC_LOGD("%s]: ", __func__);
844
845 // set nmea mask type
846 uint32_t mask = 0;
847 if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
848 mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
849 }
850 if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
851 mask |= LOC_NMEA_MASK_DEBUG_V02;
852 }
853 if (mNmeaMask != mask) {
854 mNmeaMask = mask;
855 if (mNmeaMask) {
856 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
857 if ((it->second.gnssNmeaCb != nullptr)) {
858 updateEvtMask(LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT,
859 LOC_REGISTRATION_MASK_ENABLED);
860 break;
861 }
862 }
863 }
864 }
865
866 std::string oldMoServerUrl = getMoServerUrl();
867 setSuplHostServer(ContextBase::mGps_conf.SUPL_HOST,
868 ContextBase::mGps_conf.SUPL_PORT,
869 LOC_AGPS_SUPL_SERVER);
870 setSuplHostServer(ContextBase::mGps_conf.MO_SUPL_HOST,
871 ContextBase::mGps_conf.MO_SUPL_PORT,
872 LOC_AGPS_MO_SUPL_SERVER);
873
874 // inject the configurations into modem
875 loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
876 loc_sap_cfg_s_type sapConf = ContextBase::mSap_conf;
877
878 //cache the injected configuration with GnssConfigRequested struct
879 GnssConfig gnssConfigRequested = {};
880 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT |
881 GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
882 /* Here we process an SSR. We need to set the GPS_LOCK to the proper values, as follows:
883 1. Q behavior. This is identified by mSupportNfwControl being 1. In this case
884 ContextBase::mGps_conf.GPS_LOCK is a "state", meaning it should reflect the
885 NV value. Therefore we will set the NV to ContextBase::mGps_conf.GPS_LOCK
886 2. P behavior. This is identified by mSupportNfwControl being 0. In this case
887 ContextBase::mGps_conf.GPS_LOCK is a "configuration", meaning it should hold
888 the "mask" for NI. There are two subcases:
889 a. Location enabled in GUI (1 == getAfwControlId()). We need to set
890 the NV to GNSS_CONFIG_GPS_LOCK_NONE (both MO and NI enabled)
891 b. Location disabled in GUI (0 == getAfwControlId()). We need to set
892 the NV to ContextBase::mGps_conf.GPS_LOCK (the "mask", which is SIM-card
893 specific)
894 */
895 if (mSupportNfwControl || (0 == getAfwControlId())) {
896 gnssConfigRequested.gpsLock = gpsConf.GPS_LOCK;
897 } else {
898 gnssConfigRequested.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
899 }
900 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT |
901 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
902 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
903 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
904 gnssConfigRequested.suplVersion =
905 mLocApi->convertSuplVersion(gpsConf.SUPL_VER);
906 gnssConfigRequested.lppProfile =
907 mLocApi->convertLppProfile(gpsConf.LPP_PROFILE);
908 gnssConfigRequested.aGlonassPositionProtocolMask =
909 gpsConf.A_GLONASS_POS_PROTOCOL_SELECT;
910 if (gpsConf.LPPE_CP_TECHNOLOGY) {
911 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
912 gnssConfigRequested.lppeControlPlaneMask =
913 mLocApi->convertLppeCp(gpsConf.LPPE_CP_TECHNOLOGY);
914 }
915
916 if (gpsConf.LPPE_UP_TECHNOLOGY) {
917 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
918 gnssConfigRequested.lppeUserPlaneMask =
919 mLocApi->convertLppeUp(gpsConf.LPPE_UP_TECHNOLOGY);
920 }
921 gnssConfigRequested.blacklistedSvIds.assign(mBlacklistedSvIds.begin(),
922 mBlacklistedSvIds.end());
923 mLocApi->sendMsg(new LocApiMsg(
924 [this, gpsConf, sapConf, oldMoServerUrl, gnssConfigRequested] () mutable {
925 gnssUpdateConfig(oldMoServerUrl, gnssConfigRequested, gnssConfigRequested);
926
927 // set nmea mask type
928 uint32_t mask = 0;
929 if (NMEA_PROVIDER_MP == gpsConf.NMEA_PROVIDER) {
930 mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
931 }
932 if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
933 mask |= LOC_NMEA_MASK_DEBUG_V02;
934 }
935
936 if (mask != 0) {
937 mLocApi->setNMEATypesSync(mask);
938 }
939
940 mLocApi->setXtraVersionCheckSync(gpsConf.XTRA_VERSION_CHECK);
941
942 // load tunc configuration from config file on first boot-up,
943 // e.g.: adapter.mLocConfigInfo.tuncConfigInfo.isValid is false
944 if (mLocConfigInfo.tuncConfigInfo.isValid == false) {
945 mLocConfigInfo.tuncConfigInfo.isValid = true;
946 mLocConfigInfo.tuncConfigInfo.enable =
947 (gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED == 1);
948 mLocConfigInfo.tuncConfigInfo.tuncThresholdMs =
949 (float)gpsConf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD;
950 mLocConfigInfo.tuncConfigInfo.energyBudget =
951 gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET;
952 }
953
954 mLocApi->setConstrainedTuncMode(
955 mLocConfigInfo.tuncConfigInfo.enable,
956 mLocConfigInfo.tuncConfigInfo.tuncThresholdMs,
957 mLocConfigInfo.tuncConfigInfo.energyBudget);
958
959 // load pace configuration from config file on first boot-up,
960 // e.g.: adapter.mLocConfigInfo.paceConfigInfo.isValid is false
961 if (mLocConfigInfo.paceConfigInfo.isValid == false) {
962 mLocConfigInfo.paceConfigInfo.isValid = true;
963 mLocConfigInfo.paceConfigInfo.enable =
964 (gpsConf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED==1);
965 }
966 mLocApi->setPositionAssistedClockEstimatorMode(
967 mLocConfigInfo.paceConfigInfo.enable);
968
969 // we do not support control robust location from gps.conf
970 if (mLocConfigInfo.robustLocationConfigInfo.isValid == true) {
971 mLocApi->configRobustLocation(
972 mLocConfigInfo.robustLocationConfigInfo.enable,
973 mLocConfigInfo.robustLocationConfigInfo.enableFor911);
974 }
975
976 if (sapConf.GYRO_BIAS_RANDOM_WALK_VALID ||
977 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
978 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
979 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
980 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
981 mLocApi->setSensorPropertiesSync(
982 sapConf.GYRO_BIAS_RANDOM_WALK_VALID,
983 sapConf.GYRO_BIAS_RANDOM_WALK,
984 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
985 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
986 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
987 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
988 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
989 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
990 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
991 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
992 }
993 mLocApi->setSensorPerfControlConfigSync(
994 sapConf.SENSOR_CONTROL_MODE,
995 sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
996 sapConf.SENSOR_ACCEL_BATCHES_PER_SEC,
997 sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH,
998 sapConf.SENSOR_GYRO_BATCHES_PER_SEC,
999 sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
1000 sapConf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
1001 sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
1002 sapConf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
1003 sapConf.SENSOR_ALGORITHM_CONFIG_MASK);
1004 } ));
1005 // deal with Measurement Corrections
1006 if (true == mIsMeasCorrInterfaceOpen) {
1007 initMeasCorr(true);
1008 }
1009 }
1010
gnssUpdateConfig(const std::string & oldMoServerUrl,GnssConfig & gnssConfigRequested,GnssConfig & gnssConfigNeedEngineUpdate,size_t count)1011 std::vector<LocationError> GnssAdapter::gnssUpdateConfig(const std::string& oldMoServerUrl,
1012 GnssConfig& gnssConfigRequested, GnssConfig& gnssConfigNeedEngineUpdate, size_t count) {
1013 loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
1014 size_t index = 0;
1015 LocationError err = LOCATION_ERROR_SUCCESS;
1016 std::vector<LocationError> errsList = {err};
1017 if (count > 0) {
1018 errsList.insert(errsList.begin(), count, LOCATION_ERROR_SUCCESS);
1019 }
1020
1021 std::string serverUrl = getServerUrl();
1022 std::string moServerUrl = getMoServerUrl();
1023
1024 int serverUrlLen = serverUrl.length();
1025 int moServerUrlLen = moServerUrl.length();
1026
1027 if (!ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
1028 LOC_LOGd("AGPS_CONFIG_INJECT is 0. Not setting flags for AGPS configurations");
1029 gnssConfigRequested.flags &= ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT |
1030 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
1031 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
1032 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT);
1033 }
1034
1035 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1036 if (gnssConfigNeedEngineUpdate.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1037 err = mLocApi->setGpsLockSync(gnssConfigRequested.gpsLock);
1038 if (index < count) {
1039 errsList[index] = err;
1040 }
1041 }
1042 index++;
1043 }
1044
1045 if (gnssConfigRequested.flags &
1046 GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1047 if (gnssConfigNeedEngineUpdate.flags &
1048 GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1049 if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
1050 GNSS_ASSISTANCE_TYPE_SUPL) {
1051 err = mLocApi->setServerSync(
1052 serverUrl.c_str(), serverUrlLen, LOC_AGPS_SUPL_SERVER);
1053 if (index < count) {
1054 errsList[index] = err;
1055 }
1056 if (0 != oldMoServerUrl.compare(moServerUrl)) {
1057 LocationError locErr =
1058 mLocApi->setServerSync(moServerUrl.c_str(),
1059 moServerUrlLen,
1060 LOC_AGPS_MO_SUPL_SERVER);
1061 if (locErr != LOCATION_ERROR_SUCCESS) {
1062 LOC_LOGe("Error while setting MO SUPL_HOST server:%s",
1063 moServerUrl.c_str());
1064 }
1065 }
1066 } else if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
1067 GNSS_ASSISTANCE_TYPE_C2K) {
1068 struct in_addr addr;
1069 struct hostent* hp;
1070 bool resolveAddrSuccess = true;
1071
1072 hp = gethostbyname(
1073 gnssConfigNeedEngineUpdate.assistanceServer.hostName);
1074 if (hp != NULL) { /* DNS OK */
1075 memcpy(&addr, hp->h_addr_list[0], hp->h_length);
1076 } else {
1077 /* Try IP representation */
1078 if (inet_aton(
1079 gnssConfigNeedEngineUpdate.assistanceServer.hostName,
1080 &addr) == 0) {
1081 /* IP not valid */
1082 LOC_LOGE("%s]: hostname '%s' cannot be resolved ",
1083 __func__,
1084 gnssConfigNeedEngineUpdate.assistanceServer.hostName);
1085 if (index < count) {
1086 errsList[index] = LOCATION_ERROR_INVALID_PARAMETER;
1087 }
1088 } else {
1089 resolveAddrSuccess = false;
1090 }
1091 }
1092
1093 if (resolveAddrSuccess) {
1094 unsigned int ip = htonl(addr.s_addr);
1095 err = mLocApi->setServerSync(ip,
1096 gnssConfigNeedEngineUpdate.assistanceServer.port,
1097 LOC_AGPS_CDMA_PDE_SERVER);
1098 if (index < count) {
1099 errsList[index] = err;
1100 }
1101 }
1102 }
1103 }
1104 index++;
1105 }
1106
1107 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1108 if (gnssConfigNeedEngineUpdate.flags &
1109 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1110 err = mLocApi->setSUPLVersionSync(gnssConfigRequested.suplVersion);
1111 if (index < count) {
1112 errsList[index] = err;
1113 }
1114 }
1115 index++;
1116 }
1117
1118 /* Comment out LPP injection as it's configured by MBN.
1119 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1120 if (gnssConfigNeedEngineUpdate.flags &
1121 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1122 err = mLocApi->setLPPConfigSync(gnssConfigRequested.lppProfile);
1123 if (index < count) {
1124 errsList[index] = err;
1125 }
1126 }
1127 index++;
1128 }
1129 */
1130
1131 /* Comment out LPPe injection as it's configured by MBN.
1132 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1133 if (gnssConfigNeedEngineUpdate.flags &
1134 GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1135 err = mLocApi->setLPPeProtocolCpSync(
1136 gnssConfigRequested.lppeControlPlaneMask);
1137 if (index < count) {
1138 errsList[index] = err;
1139 }
1140 }
1141 index++;
1142 }
1143
1144 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1145 if (gnssConfigNeedEngineUpdate.flags &
1146 GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1147 err = mLocApi->setLPPeProtocolUpSync(
1148 gnssConfigRequested.lppeUserPlaneMask);
1149 if (index < count) {
1150 errsList[index] = err;
1151 }
1152 }
1153 index++;
1154 }
1155 */
1156
1157 if (gnssConfigRequested.flags &
1158 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1159 if (gnssConfigNeedEngineUpdate.flags &
1160 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1161 err = mLocApi->setAGLONASSProtocolSync(
1162 gnssConfigRequested.aGlonassPositionProtocolMask);
1163 if (index < count) {
1164 errsList[index] = err;
1165 }
1166 }
1167 index++;
1168 }
1169 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
1170 // Check if feature is supported
1171 if (!ContextBase::isFeatureSupported(
1172 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1173 LOC_LOGe("Feature constellation enablement not supported.");
1174 err = LOCATION_ERROR_NOT_SUPPORTED;
1175 } else {
1176 // Send the SV ID Config to Modem
1177 mBlacklistedSvIds.assign(gnssConfigRequested.blacklistedSvIds.begin(),
1178 gnssConfigRequested.blacklistedSvIds.end());
1179 err = gnssSvIdConfigUpdateSync(gnssConfigRequested.blacklistedSvIds);
1180 if (LOCATION_ERROR_SUCCESS != err) {
1181 LOC_LOGe("Failed to send config to modem, err %d", err);
1182 }
1183 }
1184 if (index < count) {
1185 errsList[index] = err;
1186 }
1187 index++;
1188 }
1189 if (gnssConfigRequested.flags &
1190 GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1191 if (gnssConfigNeedEngineUpdate.flags &
1192 GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1193 err = mLocApi->setEmergencyExtensionWindowSync(
1194 gnssConfigRequested.emergencyExtensionSeconds);
1195 if (index < count) {
1196 errsList[index] = err;
1197 }
1198 }
1199 index++;
1200 }
1201 return errsList;
1202 }
1203
1204 uint32_t*
gnssUpdateConfigCommand(GnssConfig config)1205 GnssAdapter::gnssUpdateConfigCommand(GnssConfig config)
1206 {
1207 // count the number of bits set
1208 GnssConfigFlagsMask flagsCopy = config.flags;
1209 size_t count = 0;
1210 while (flagsCopy > 0) {
1211 if (flagsCopy & 1) {
1212 count++;
1213 }
1214 flagsCopy >>= 1;
1215 }
1216 std::string idsString = "[";
1217 uint32_t* ids = NULL;
1218 if (count > 0) {
1219 ids = new uint32_t[count];
1220 if (ids == nullptr) {
1221 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1222 return nullptr;
1223 }
1224 for (size_t i=0; i < count; ++i) {
1225 ids[i] = generateSessionId();
1226 IF_LOC_LOGD {
1227 idsString += std::to_string(ids[i]) + " ";
1228 }
1229 }
1230 }
1231 idsString += "]";
1232
1233 LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
1234
1235 struct MsgGnssUpdateConfig : public LocMsg {
1236 GnssAdapter& mAdapter;
1237 LocApiBase& mApi;
1238 GnssConfig mConfig;
1239 size_t mCount;
1240 uint32_t* mIds;
1241 inline MsgGnssUpdateConfig(GnssAdapter& adapter,
1242 LocApiBase& api,
1243 GnssConfig config,
1244 uint32_t* ids,
1245 size_t count) :
1246 LocMsg(),
1247 mAdapter(adapter),
1248 mApi(api),
1249 mConfig(config),
1250 mCount(count),
1251 mIds(ids) {}
1252 inline MsgGnssUpdateConfig(const MsgGnssUpdateConfig& obj) :
1253 MsgGnssUpdateConfig(obj.mAdapter, obj.mApi, obj.mConfig,
1254 new uint32_t[obj.mCount], obj.mCount) {
1255 if (mIds != nullptr) {
1256 for (int i = 0; i < mCount; ++i) {
1257 mIds[i] = obj.mIds[i];
1258 }
1259 }
1260 }
1261 inline virtual ~MsgGnssUpdateConfig()
1262 {
1263 delete[] mIds;
1264 }
1265
1266 inline virtual void proc() const {
1267 if (!mAdapter.isEngineCapabilitiesKnown()) {
1268 mAdapter.mPendingMsgs.push_back(new MsgGnssUpdateConfig(*this));
1269 return;
1270 }
1271 GnssAdapter& adapter = mAdapter;
1272 size_t countOfConfigs = mCount;
1273 GnssConfig gnssConfigRequested = mConfig;
1274 GnssConfig gnssConfigNeedEngineUpdate = mConfig;
1275
1276 std::vector<uint32_t> sessionIds;
1277 sessionIds.assign(mIds, mIds + mCount);
1278 std::vector<LocationError> errs(mCount, LOCATION_ERROR_SUCCESS);
1279 int index = 0;
1280
1281 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1282 GnssConfigGpsLock newGpsLock = gnssConfigRequested.gpsLock;
1283
1284 newGpsLock |= GNSS_CONFIG_GPS_LOCK_MO;
1285 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
1286 /* If we get here it means that the changes in the framework to request for
1287 'P' behavior were made, and therefore we need to "behave" as in 'P'
1288 However, we need to determine if enableCommand function has already been
1289 called, since it could get called before this function.*/
1290 if (0 != mAdapter.getAfwControlId()) {
1291 /* enableCommand function has already been called since getAfwControlId
1292 returns non zero. Now there are two possible cases:
1293 1. This is the first time this function is called
1294 (mSupportNfwControl is true). We need to behave as in 'P', but
1295 for the first time, meaning MO was enabled, but NI was not, so
1296 we need to unlock NI
1297 2. This is not the first time this function is called, meaning we
1298 are already behaving as in 'P'. No need to update the configuration
1299 in this case (return to 'P' code) */
1300 if (mAdapter.mSupportNfwControl) {
1301 // case 1 above
1302 newGpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
1303 } else {
1304 // case 2 above
1305 gnssConfigNeedEngineUpdate.flags &= ~(GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT);
1306 }
1307 }
1308 gnssConfigRequested.gpsLock = newGpsLock;
1309 mAdapter.mSupportNfwControl = false;
1310 index++;
1311 }
1312 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1313 uint32_t newSuplVersion =
1314 mAdapter.convertSuplVersion(gnssConfigRequested.suplVersion);
1315 ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
1316 index++;
1317 }
1318 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1319 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
1320 mAdapter.setSuplHostServer(mConfig.assistanceServer.hostName,
1321 mConfig.assistanceServer.port,
1322 LOC_AGPS_SUPL_SERVER);
1323 } else {
1324 LOC_LOGE("%s]: Not a valid gnss assistance type %u",
1325 __func__, mConfig.assistanceServer.type);
1326 errs.at(index) = LOCATION_ERROR_INVALID_PARAMETER;
1327 gnssConfigNeedEngineUpdate.flags &=
1328 ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT);
1329 }
1330 index++;
1331 }
1332 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1333 uint32_t newLppProfile = mAdapter.convertLppProfile(gnssConfigRequested.lppProfile);
1334 ContextBase::mGps_conf.LPP_PROFILE = newLppProfile;
1335 index++;
1336 }
1337 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1338 uint32_t newLppeControlPlaneMask =
1339 mAdapter.convertLppeCp(gnssConfigRequested.lppeControlPlaneMask);
1340 ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
1341 index++;
1342 }
1343 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1344 uint32_t newLppeUserPlaneMask =
1345 mAdapter.convertLppeUp(gnssConfigRequested.lppeUserPlaneMask);
1346 ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
1347 index++;
1348 }
1349 if (gnssConfigRequested.flags &
1350 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1351 uint32_t newAGloProtMask =
1352 mAdapter.convertAGloProt(gnssConfigRequested.aGlonassPositionProtocolMask);
1353 ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
1354 index++;
1355 }
1356 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1357 uint32_t newEP4ES = mAdapter.convertEP4ES(
1358 gnssConfigRequested.emergencyPdnForEmergencySupl);
1359 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
1360 ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
1361 }
1362 index++;
1363 }
1364 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1365 uint32_t newSuplEs = mAdapter.convertSuplEs(
1366 gnssConfigRequested.suplEmergencyServices);
1367 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
1368 ContextBase::mGps_conf.SUPL_ES = newSuplEs;
1369 }
1370 index++;
1371 }
1372 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1373 uint32_t newSuplMode = mAdapter.convertSuplMode(gnssConfigRequested.suplModeMask);
1374 ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
1375 mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
1376 index++;
1377 }
1378
1379 LocApiCollectiveResponse *configCollectiveResponse = new LocApiCollectiveResponse(
1380 *adapter.getContext(),
1381 [&adapter, sessionIds, countOfConfigs] (std::vector<LocationError> errs) {
1382
1383 std::vector<uint32_t> ids(sessionIds);
1384 adapter.reportResponse(countOfConfigs, errs.data(), ids.data());
1385 });
1386
1387 mApi.sendMsg(new LocApiMsg(
1388 [&adapter, gnssConfigRequested, gnssConfigNeedEngineUpdate,
1389 countOfConfigs, configCollectiveResponse, errs] () mutable {
1390 std::vector<LocationError> errsList = adapter.gnssUpdateConfig("",
1391 gnssConfigRequested, gnssConfigNeedEngineUpdate, countOfConfigs);
1392
1393 configCollectiveResponse->returnToSender(errsList);
1394 }));
1395 }
1396 };
1397
1398 if (NULL != ids) {
1399 sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
1400 } else {
1401 LOC_LOGE("%s]: No GNSS config items to update", __func__);
1402 }
1403
1404 return ids;
1405 }
1406
1407 void
gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource> & blacklistedSvIds)1408 GnssAdapter::gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource>& blacklistedSvIds)
1409 {
1410 // Clear the existing config
1411 memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1412
1413 // Convert the sv id lists to masks
1414 bool convertSuccess = convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1415
1416 // Now send to Modem if conversion successful
1417 if (convertSuccess) {
1418 gnssSvIdConfigUpdate();
1419 } else {
1420 LOC_LOGe("convertToGnssSvIdConfig failed");
1421 }
1422 }
1423
1424 void
gnssSvIdConfigUpdate()1425 GnssAdapter::gnssSvIdConfigUpdate()
1426 {
1427 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1428 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1429 mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1430 mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
1431 mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
1432 // Now set required blacklisted SVs
1433 mLocApi->setBlacklistSv(mGnssSvIdConfig);
1434 }
1435
1436 LocationError
gnssSvIdConfigUpdateSync(const std::vector<GnssSvIdSource> & blacklistedSvIds)1437 GnssAdapter::gnssSvIdConfigUpdateSync(const std::vector<GnssSvIdSource>& blacklistedSvIds)
1438 {
1439 // Clear the existing config
1440 memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1441
1442 // Convert the sv id lists to masks
1443 convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1444
1445 // Now send to Modem
1446 return gnssSvIdConfigUpdateSync();
1447 }
1448
1449 LocationError
gnssSvIdConfigUpdateSync()1450 GnssAdapter::gnssSvIdConfigUpdateSync()
1451 {
1452 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1453 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1454 mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1455 mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
1456 mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
1457
1458 // Now set required blacklisted SVs
1459 return mLocApi->setBlacklistSvSync(mGnssSvIdConfig);
1460 }
1461
1462 uint32_t*
gnssGetConfigCommand(GnssConfigFlagsMask configMask)1463 GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) {
1464
1465 // count the number of bits set
1466 GnssConfigFlagsMask flagsCopy = configMask;
1467 size_t count = 0;
1468 while (flagsCopy > 0) {
1469 if (flagsCopy & 1) {
1470 count++;
1471 }
1472 flagsCopy >>= 1;
1473 }
1474 std::string idsString = "[";
1475 uint32_t* ids = NULL;
1476 if (count > 0) {
1477 ids = new uint32_t[count];
1478 if (nullptr == ids) {
1479 LOC_LOGe("new allocation failed, fatal error.");
1480 return nullptr;
1481 }
1482 for (size_t i=0; i < count; ++i) {
1483 ids[i] = generateSessionId();
1484 IF_LOC_LOGD {
1485 idsString += std::to_string(ids[i]) + " ";
1486 }
1487 }
1488 }
1489 idsString += "]";
1490
1491 LOC_LOGd("ids %s flags 0x%X", idsString.c_str(), configMask);
1492
1493 struct MsgGnssGetConfig : public LocMsg {
1494 GnssAdapter& mAdapter;
1495 LocApiBase& mApi;
1496 GnssConfigFlagsMask mConfigMask;
1497 uint32_t* mIds;
1498 size_t mCount;
1499 inline MsgGnssGetConfig(GnssAdapter& adapter,
1500 LocApiBase& api,
1501 GnssConfigFlagsMask configMask,
1502 uint32_t* ids,
1503 size_t count) :
1504 LocMsg(),
1505 mAdapter(adapter),
1506 mApi(api),
1507 mConfigMask(configMask),
1508 mIds(ids),
1509 mCount(count) {}
1510
1511 inline MsgGnssGetConfig(const MsgGnssGetConfig& obj) :
1512 MsgGnssGetConfig(obj.mAdapter, obj.mApi, obj.mConfigMask,
1513 new uint32_t[obj.mCount], obj.mCount) {
1514 if (mIds != nullptr) {
1515 for (int i = 0; i < mCount; ++i) {
1516 mIds[i] = obj.mIds[i];
1517 }
1518 }
1519 }
1520 inline virtual ~MsgGnssGetConfig()
1521 {
1522 delete[] mIds;
1523 }
1524 inline virtual void proc() const {
1525 if (!mAdapter.isEngineCapabilitiesKnown()) {
1526 mAdapter.mPendingMsgs.push_back(new MsgGnssGetConfig(*this));
1527 return;
1528 }
1529 LocationError* errs = new LocationError[mCount];
1530 LocationError err = LOCATION_ERROR_SUCCESS;
1531 uint32_t index = 0;
1532
1533 if (nullptr == errs) {
1534 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1535 return;
1536 }
1537
1538 if (mConfigMask & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1539 if (index < mCount) {
1540 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1541 }
1542 }
1543 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1544 if (index < mCount) {
1545 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1546 }
1547 }
1548 if (mConfigMask & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1549 if (index < mCount) {
1550 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1551 }
1552 }
1553 if (mConfigMask & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1554 if (index < mCount) {
1555 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1556 }
1557 }
1558 if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1559 if (index < mCount) {
1560 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1561 }
1562 }
1563 if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1564 if (index < mCount) {
1565 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1566 }
1567 }
1568 if (mConfigMask & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1569 if (index < mCount) {
1570 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1571 }
1572 }
1573 if (mConfigMask & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1574 if (index < mCount) {
1575 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1576 }
1577 }
1578 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1579 if (index < mCount) {
1580 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1581 }
1582 }
1583 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1584 err = LOCATION_ERROR_NOT_SUPPORTED;
1585 if (index < mCount) {
1586 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1587 }
1588 }
1589 if (mConfigMask & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
1590 // Check if feature is supported
1591 if (!ContextBase::isFeatureSupported(
1592 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1593 LOC_LOGe("Feature not supported.");
1594 err = LOCATION_ERROR_NOT_SUPPORTED;
1595 } else {
1596 // Send request to Modem to fetch the config
1597 mApi.getBlacklistSv();
1598 err = LOCATION_ERROR_SUCCESS;
1599 }
1600 if (index < mCount) {
1601 errs[index++] = err;
1602 }
1603 }
1604 if (mConfigMask & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1605 err = LOCATION_ERROR_NOT_SUPPORTED;
1606 if (index < mCount) {
1607 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1608 }
1609 }
1610 if (mConfigMask & GNSS_CONFIG_FLAGS_ROBUST_LOCATION_BIT) {
1611 uint32_t sessionId = *(mIds+index);
1612 LocApiResponse* locApiResponse =
1613 new LocApiResponse(*mAdapter.getContext(),
1614 [this, sessionId] (LocationError err) {
1615 mAdapter.reportResponse(err, sessionId);});
1616 if (!locApiResponse) {
1617 LOC_LOGe("memory alloc failed");
1618 mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
1619 } else {
1620 mApi.getRobustLocationConfig(sessionId, locApiResponse);
1621 }
1622 }
1623
1624 if (mConfigMask & GNSS_CONFIG_FLAGS_MIN_GPS_WEEK_BIT) {
1625 uint32_t sessionId = *(mIds+index);
1626 LocApiResponse* locApiResponse =
1627 new LocApiResponse(*mAdapter.getContext(),
1628 [this, sessionId] (LocationError err) {
1629 mAdapter.reportResponse(err, sessionId);});
1630 if (!locApiResponse) {
1631 LOC_LOGe("memory alloc failed");
1632 mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
1633 } else {
1634 mApi.getMinGpsWeek(sessionId, locApiResponse);
1635 }
1636 }
1637
1638 mAdapter.reportResponse(index, errs, mIds);
1639 delete[] errs;
1640
1641 }
1642 };
1643
1644 if (NULL != ids) {
1645 sendMsg(new MsgGnssGetConfig(*this, *mLocApi, configMask, ids, count));
1646 } else {
1647 LOC_LOGe("No GNSS config items to Get");
1648 }
1649
1650 return ids;
1651 }
1652
1653 bool
convertToGnssSvIdConfig(const std::vector<GnssSvIdSource> & blacklistedSvIds,GnssSvIdConfig & config)1654 GnssAdapter::convertToGnssSvIdConfig(
1655 const std::vector<GnssSvIdSource>& blacklistedSvIds, GnssSvIdConfig& config)
1656 {
1657 bool retVal = false;
1658 config.size = sizeof(GnssSvIdConfig);
1659
1660 // Empty vector => Clear any previous blacklisted SVs
1661 if (0 == blacklistedSvIds.size()) {
1662 config.gloBlacklistSvMask = 0;
1663 config.bdsBlacklistSvMask = 0;
1664 config.qzssBlacklistSvMask = 0;
1665 config.galBlacklistSvMask = 0;
1666 config.sbasBlacklistSvMask = 0;
1667 config.navicBlacklistSvMask = 0;
1668 retVal = true;
1669 } else {
1670 // Parse the vector and convert SV IDs to mask values
1671 for (GnssSvIdSource source : blacklistedSvIds) {
1672 uint64_t* svMaskPtr = NULL;
1673 GnssSvId initialSvId = 0;
1674 uint16_t svIndexOffset = 0;
1675 switch(source.constellation) {
1676 case GNSS_SV_TYPE_GLONASS:
1677 svMaskPtr = &config.gloBlacklistSvMask;
1678 initialSvId = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID;
1679 break;
1680 case GNSS_SV_TYPE_BEIDOU:
1681 svMaskPtr = &config.bdsBlacklistSvMask;
1682 initialSvId = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID;
1683 break;
1684 case GNSS_SV_TYPE_QZSS:
1685 svMaskPtr = &config.qzssBlacklistSvMask;
1686 initialSvId = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID;
1687 break;
1688 case GNSS_SV_TYPE_GALILEO:
1689 svMaskPtr = &config.galBlacklistSvMask;
1690 initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID;
1691 break;
1692 case GNSS_SV_TYPE_SBAS:
1693 // SBAS does not support enable/disable whole constellation
1694 // so do not set up svTypeMask for SBAS
1695 svMaskPtr = &config.sbasBlacklistSvMask;
1696 // SBAS currently has two ranges
1697 // range of SV id: 120 to 158 and 183 to 191
1698 if (0 == source.svId) {
1699 LOC_LOGd("blacklist all SBAS SV");
1700 } else if (source.svId >= GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID) {
1701 // handle SV id in range of 183 to 191
1702 initialSvId = GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID;
1703 svIndexOffset = GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH;
1704 } else if ((source.svId >= GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID) &&
1705 (source.svId < (GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID +
1706 GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH))){
1707 // handle SV id in range of 120 to 158
1708 initialSvId = GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID;
1709 } else {
1710 LOC_LOGe("invalid SBAS sv id %d", source.svId);
1711 svMaskPtr = nullptr;
1712 }
1713 break;
1714 case GNSS_SV_TYPE_NAVIC:
1715 svMaskPtr = &config.navicBlacklistSvMask;
1716 initialSvId = GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID;
1717 break;
1718 default:
1719 break;
1720 }
1721
1722 if (NULL == svMaskPtr) {
1723 LOC_LOGe("Invalid constellation %d", source.constellation);
1724 } else {
1725 // SV ID 0 = All SV IDs
1726 if (0 == source.svId) {
1727 *svMaskPtr = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1728 } else if (source.svId < initialSvId || source.svId >= initialSvId + 64) {
1729 LOC_LOGe("Invalid sv id %d for sv type %d",
1730 source.svId, source.constellation);
1731 } else {
1732 uint32_t shiftCnt = source.svId + svIndexOffset - initialSvId;
1733 *svMaskPtr |= (1ULL << shiftCnt);
1734 }
1735 }
1736 }
1737
1738 // Return true if any one source is valid
1739 if (0 != config.gloBlacklistSvMask ||
1740 0 != config.bdsBlacklistSvMask ||
1741 0 != config.galBlacklistSvMask ||
1742 0 != config.qzssBlacklistSvMask ||
1743 0 != config.sbasBlacklistSvMask ||
1744 0 != config.navicBlacklistSvMask) {
1745 retVal = true;
1746 }
1747 }
1748
1749 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1750 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1751 config.bdsBlacklistSvMask, config.gloBlacklistSvMask,
1752 config.qzssBlacklistSvMask, config.galBlacklistSvMask,
1753 config.sbasBlacklistSvMask, config.navicBlacklistSvMask);
1754
1755 return retVal;
1756 }
1757
convertFromGnssSvIdConfig(const GnssSvIdConfig & svConfig,std::vector<GnssSvIdSource> & blacklistedSvIds)1758 void GnssAdapter::convertFromGnssSvIdConfig(
1759 const GnssSvIdConfig& svConfig, std::vector<GnssSvIdSource>& blacklistedSvIds)
1760 {
1761 // Convert blacklisted SV mask values to vectors
1762 if (svConfig.bdsBlacklistSvMask) {
1763 convertGnssSvIdMaskToList(
1764 svConfig.bdsBlacklistSvMask, blacklistedSvIds,
1765 GNSS_SV_CONFIG_BDS_INITIAL_SV_ID, GNSS_SV_TYPE_BEIDOU);
1766 }
1767 if (svConfig.galBlacklistSvMask) {
1768 convertGnssSvIdMaskToList(
1769 svConfig.galBlacklistSvMask, blacklistedSvIds,
1770 GNSS_SV_CONFIG_GAL_INITIAL_SV_ID, GNSS_SV_TYPE_GALILEO);
1771 }
1772 if (svConfig.gloBlacklistSvMask) {
1773 convertGnssSvIdMaskToList(
1774 svConfig.gloBlacklistSvMask, blacklistedSvIds,
1775 GNSS_SV_CONFIG_GLO_INITIAL_SV_ID, GNSS_SV_TYPE_GLONASS);
1776 }
1777 if (svConfig.qzssBlacklistSvMask) {
1778 convertGnssSvIdMaskToList(
1779 svConfig.qzssBlacklistSvMask, blacklistedSvIds,
1780 GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID, GNSS_SV_TYPE_QZSS);
1781 }
1782 if (svConfig.sbasBlacklistSvMask) {
1783 convertGnssSvIdMaskToList(
1784 svConfig.sbasBlacklistSvMask, blacklistedSvIds,
1785 GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID, GNSS_SV_TYPE_SBAS);
1786 }
1787 if (svConfig.navicBlacklistSvMask) {
1788 convertGnssSvIdMaskToList(
1789 svConfig.navicBlacklistSvMask, blacklistedSvIds,
1790 GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID, GNSS_SV_TYPE_NAVIC);
1791 }
1792
1793 }
1794
convertGnssSvIdMaskToList(uint64_t svIdMask,std::vector<GnssSvIdSource> & svIds,GnssSvId initialSvId,GnssSvType svType)1795 void GnssAdapter::convertGnssSvIdMaskToList(
1796 uint64_t svIdMask, std::vector<GnssSvIdSource>& svIds,
1797 GnssSvId initialSvId, GnssSvType svType)
1798 {
1799 GnssSvIdSource source = {};
1800 source.size = sizeof(GnssSvIdSource);
1801 source.constellation = svType;
1802
1803 // SV ID 0 => All SV IDs in mask
1804 if (GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK == svIdMask) {
1805 LOC_LOGd("blacklist all SVs in constellation %d", source.constellation);
1806 source.svId = 0;
1807 svIds.push_back(source);
1808 return;
1809 }
1810
1811 // Convert each bit in svIdMask to vector entry
1812 uint32_t bitNumber = 0;
1813 while (svIdMask > 0) {
1814 if (svIdMask & 0x1) {
1815 source.svId = bitNumber + initialSvId;
1816 // SBAS has two ranges:
1817 // SBAS - SV 120 to 158, maps to 0 to 38
1818 // SV 183 to 191, maps to 39 to 47
1819 // #define GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID 120
1820 // #define GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH 39
1821 // #define GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID 183
1822 if (svType == GNSS_SV_TYPE_SBAS) {
1823 if (bitNumber >= GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH) {
1824 source.svId = bitNumber - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH +
1825 GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID;
1826 }
1827 }
1828 svIds.push_back(source);
1829 }
1830 bitNumber++;
1831 svIdMask >>= 1;
1832 }
1833 }
1834
reportGnssSvIdConfigEvent(const GnssSvIdConfig & config)1835 void GnssAdapter::reportGnssSvIdConfigEvent(const GnssSvIdConfig& config)
1836 {
1837 struct MsgReportGnssSvIdConfig : public LocMsg {
1838 GnssAdapter& mAdapter;
1839 const GnssSvIdConfig mConfig;
1840 inline MsgReportGnssSvIdConfig(GnssAdapter& adapter,
1841 const GnssSvIdConfig& config) :
1842 LocMsg(),
1843 mAdapter(adapter),
1844 mConfig(config) {}
1845 inline virtual void proc() const {
1846 mAdapter.reportGnssSvIdConfig(mConfig);
1847 }
1848 };
1849
1850 sendMsg(new MsgReportGnssSvIdConfig(*this, config));
1851 }
1852
reportGnssSvIdConfig(const GnssSvIdConfig & svIdConfig)1853 void GnssAdapter::reportGnssSvIdConfig(const GnssSvIdConfig& svIdConfig)
1854 {
1855 GnssConfig config = {};
1856 config.size = sizeof(GnssConfig);
1857
1858 // Invoke control clients config callback
1859 if (nullptr != mControlCallbacks.gnssConfigCb &&
1860 svIdConfig.size == sizeof(GnssSvIdConfig)) {
1861
1862 convertFromGnssSvIdConfig(svIdConfig, config.blacklistedSvIds);
1863 if (config.blacklistedSvIds.size() > 0) {
1864 config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1865 }
1866 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64 ", "
1867 "qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1868 svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask,
1869 svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask,
1870 svIdConfig.sbasBlacklistSvMask, svIdConfig.navicBlacklistSvMask);
1871 // use 0 session id to indicate that receiver does not yet care about session id
1872 mControlCallbacks.gnssConfigCb(0, config);
1873 } else {
1874 LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
1875 }
1876 }
1877
1878 void
gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)1879 GnssAdapter::gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)
1880 {
1881 struct MsgGnssUpdateSvTypeConfig : public LocMsg {
1882 GnssAdapter* mAdapter;
1883 LocApiBase* mApi;
1884 GnssSvTypeConfig mConfig;
1885 inline MsgGnssUpdateSvTypeConfig(
1886 GnssAdapter* adapter,
1887 LocApiBase* api,
1888 GnssSvTypeConfig& config) :
1889 LocMsg(),
1890 mAdapter(adapter),
1891 mApi(api),
1892 mConfig(config) {}
1893 inline virtual void proc() const {
1894 if (!mAdapter->isEngineCapabilitiesKnown()) {
1895 mAdapter->mPendingMsgs.push_back(new MsgGnssUpdateSvTypeConfig(*this));
1896 return;
1897 }
1898 // Check if feature is supported
1899 if (!ContextBase::isFeatureSupported(
1900 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1901 LOC_LOGe("Feature not supported.");
1902 } else {
1903 // Send update request to modem
1904 mAdapter->gnssSvTypeConfigUpdate(mConfig);
1905 }
1906 }
1907 };
1908
1909 sendMsg(new MsgGnssUpdateSvTypeConfig(this, mLocApi, config));
1910 }
1911
1912 void
gnssSvTypeConfigUpdate(const GnssSvTypeConfig & config)1913 GnssAdapter::gnssSvTypeConfigUpdate(const GnssSvTypeConfig& config)
1914 {
1915 // Gather bits removed from enabled mask
1916 GnssSvTypesMask enabledRemoved = mGnssSvTypeConfig.enabledSvTypesMask &
1917 (mGnssSvTypeConfig.enabledSvTypesMask ^ config.enabledSvTypesMask);
1918 // Send reset if any constellation is removed from the enabled list
1919 bool sendReset = (enabledRemoved != 0);
1920 // Save new config and update
1921 gnssSetSvTypeConfig(config);
1922 gnssSvTypeConfigUpdate(sendReset);
1923 }
1924
1925 void
gnssSvTypeConfigUpdate(bool sendReset)1926 GnssAdapter::gnssSvTypeConfigUpdate(bool sendReset)
1927 {
1928 LOC_LOGd("size %" PRIu32" constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64
1929 ", sendReset %d",
1930 mGnssSvTypeConfig.size, mGnssSvTypeConfig.blacklistedSvTypesMask,
1931 mGnssSvTypeConfig.enabledSvTypesMask, sendReset);
1932
1933 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1934 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", Navic 0x%" PRIx64,
1935 mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1936 mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
1937 mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
1938
1939 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1940 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64,
1941 mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1942 mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
1943 mGnssSvIdConfig.sbasBlacklistSvMask);
1944
1945 if (mGnssSvTypeConfig.size == sizeof(mGnssSvTypeConfig)) {
1946
1947 if (sendReset) {
1948 mLocApi->resetConstellationControl();
1949 }
1950
1951 GnssSvIdConfig blacklistConfig = {};
1952 // Revert to previously blacklisted SVs for each enabled constellation
1953 blacklistConfig = mGnssSvIdConfig;
1954 // Blacklist all SVs for each disabled constellation
1955 if (mGnssSvTypeConfig.blacklistedSvTypesMask) {
1956 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GLO_BIT) {
1957 blacklistConfig.gloBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1958 }
1959 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_BDS_BIT) {
1960 blacklistConfig.bdsBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1961 }
1962 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_QZSS_BIT) {
1963 blacklistConfig.qzssBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1964 }
1965 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GAL_BIT) {
1966 blacklistConfig.galBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1967 }
1968 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_NAVIC_BIT) {
1969 blacklistConfig.navicBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1970 }
1971 }
1972
1973 // Send blacklist info
1974 mLocApi->setBlacklistSv(blacklistConfig);
1975
1976 // Send only enabled constellation config
1977 if (mGnssSvTypeConfig.enabledSvTypesMask) {
1978 GnssSvTypeConfig svTypeConfig = {sizeof(GnssSvTypeConfig), 0, 0};
1979 svTypeConfig.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask;
1980 mLocApi->setConstellationControl(svTypeConfig);
1981 }
1982 }
1983 }
1984
1985 void
gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)1986 GnssAdapter::gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)
1987 {
1988 struct MsgGnssGetSvTypeConfig : public LocMsg {
1989 GnssAdapter* mAdapter;
1990 LocApiBase* mApi;
1991 GnssSvTypeConfigCallback mCallback;
1992 inline MsgGnssGetSvTypeConfig(
1993 GnssAdapter* adapter,
1994 LocApiBase* api,
1995 GnssSvTypeConfigCallback callback) :
1996 LocMsg(),
1997 mAdapter(adapter),
1998 mApi(api),
1999 mCallback(callback) {}
2000 inline virtual void proc() const {
2001 if (!mAdapter->isEngineCapabilitiesKnown()) {
2002 mAdapter->mPendingMsgs.push_back(new MsgGnssGetSvTypeConfig(*this));
2003 return;
2004 }
2005 if (!ContextBase::isFeatureSupported(
2006 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
2007 LOC_LOGe("Feature not supported.");
2008 } else {
2009 // Save the callback
2010 mAdapter->gnssSetSvTypeConfigCallback(mCallback);
2011 // Send GET request to modem
2012 mApi->getConstellationControl();
2013 }
2014 }
2015 };
2016
2017 sendMsg(new MsgGnssGetSvTypeConfig(this, mLocApi, callback));
2018 }
2019
2020 void
gnssResetSvTypeConfigCommand()2021 GnssAdapter::gnssResetSvTypeConfigCommand()
2022 {
2023 struct MsgGnssResetSvTypeConfig : public LocMsg {
2024 GnssAdapter* mAdapter;
2025 LocApiBase* mApi;
2026 inline MsgGnssResetSvTypeConfig(
2027 GnssAdapter* adapter,
2028 LocApiBase* api) :
2029 LocMsg(),
2030 mAdapter(adapter),
2031 mApi(api) {}
2032 inline virtual void proc() const {
2033 if (!mAdapter->isEngineCapabilitiesKnown()) {
2034 mAdapter->mPendingMsgs.push_back(new MsgGnssResetSvTypeConfig(*this));
2035 return;
2036 }
2037 if (!ContextBase::isFeatureSupported(
2038 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
2039 LOC_LOGe("Feature not supported.");
2040 } else {
2041 // Reset constellation config
2042 mAdapter->gnssSetSvTypeConfig({sizeof(GnssSvTypeConfig), 0, 0});
2043 // Re-enforce SV blacklist config
2044 mAdapter->gnssSvIdConfigUpdate();
2045 // Send reset request to modem
2046 mApi->resetConstellationControl();
2047 }
2048 }
2049 };
2050
2051 sendMsg(new MsgGnssResetSvTypeConfig(this, mLocApi));
2052 }
2053
reportGnssSvTypeConfigEvent(const GnssSvTypeConfig & config)2054 void GnssAdapter::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config)
2055 {
2056 struct MsgReportGnssSvTypeConfig : public LocMsg {
2057 GnssAdapter& mAdapter;
2058 const GnssSvTypeConfig mConfig;
2059 inline MsgReportGnssSvTypeConfig(GnssAdapter& adapter,
2060 const GnssSvTypeConfig& config) :
2061 LocMsg(),
2062 mAdapter(adapter),
2063 mConfig(config) {}
2064 inline virtual void proc() const {
2065 mAdapter.reportGnssSvTypeConfig(mConfig);
2066 }
2067 };
2068
2069 sendMsg(new MsgReportGnssSvTypeConfig(*this, config));
2070 }
2071
reportGnssSvTypeConfig(const GnssSvTypeConfig & config)2072 void GnssAdapter::reportGnssSvTypeConfig(const GnssSvTypeConfig& config)
2073 {
2074 // Invoke Get SV Type Callback
2075 if (NULL != mGnssSvTypeConfigCb &&
2076 config.size == sizeof(GnssSvTypeConfig)) {
2077 LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
2078 config.blacklistedSvTypesMask, config.enabledSvTypesMask);
2079 mGnssSvTypeConfigCb(config);
2080 } else {
2081 LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
2082 }
2083 }
2084
deleteAidingData(const GnssAidingData & data,uint32_t sessionId)2085 void GnssAdapter::deleteAidingData(const GnssAidingData &data, uint32_t sessionId) {
2086 mLocApi->deleteAidingData(data, new LocApiResponse(*getContext(),
2087 [this, sessionId] (LocationError err) {
2088 reportResponse(err, sessionId);
2089 }));
2090 }
2091
2092 uint32_t
gnssDeleteAidingDataCommand(GnssAidingData & data)2093 GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
2094 {
2095 uint32_t sessionId = generateSessionId();
2096 LOC_LOGD("%s]: id %u", __func__, sessionId);
2097
2098 struct MsgDeleteAidingData : public LocMsg {
2099 GnssAdapter& mAdapter;
2100 uint32_t mSessionId;
2101 GnssAidingData mData;
2102 inline MsgDeleteAidingData(GnssAdapter& adapter,
2103 uint32_t sessionId,
2104 GnssAidingData& data) :
2105 LocMsg(),
2106 mAdapter(adapter),
2107 mSessionId(sessionId),
2108 mData(data) {}
2109 inline virtual void proc() const {
2110 if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) != 0) {
2111 mAdapter.deleteAidingData(mData, mSessionId);
2112
2113 SystemStatus* s = mAdapter.getSystemStatus();
2114 if ((nullptr != s) && (mData.deleteAll)) {
2115 s->setDefaultGnssEngineStates();
2116 }
2117 }
2118
2119 mAdapter.mEngHubProxy->gnssDeleteAidingData(mData);
2120 }
2121 };
2122
2123 sendMsg(new MsgDeleteAidingData(*this, sessionId, data));
2124 return sessionId;
2125 }
2126
2127 void
gnssUpdateXtraThrottleCommand(const bool enabled)2128 GnssAdapter::gnssUpdateXtraThrottleCommand(const bool enabled)
2129 {
2130 LOC_LOGD("%s] enabled:%d", __func__, enabled);
2131
2132 struct UpdateXtraThrottleMsg : public LocMsg {
2133 GnssAdapter& mAdapter;
2134 const bool mEnabled;
2135 inline UpdateXtraThrottleMsg(GnssAdapter& adapter, const bool enabled) :
2136 LocMsg(),
2137 mAdapter(adapter),
2138 mEnabled(enabled) {}
2139 inline virtual void proc() const {
2140 mAdapter.mXtraObserver.updateXtraThrottle(mEnabled);
2141 }
2142 };
2143
2144 sendMsg(new UpdateXtraThrottleMsg(*this, enabled));
2145 }
2146
2147 void
injectLocationCommand(double latitude,double longitude,float accuracy)2148 GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
2149 {
2150 LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
2151 __func__, latitude, longitude, accuracy);
2152
2153 struct MsgInjectLocation : public LocMsg {
2154 LocApiBase& mApi;
2155 ContextBase& mContext;
2156 BlockCPIInfo& mBlockCPI;
2157 double mLatitude;
2158 double mLongitude;
2159 float mAccuracy;
2160 inline MsgInjectLocation(LocApiBase& api,
2161 ContextBase& context,
2162 BlockCPIInfo& blockCPIInfo,
2163 double latitude,
2164 double longitude,
2165 float accuracy) :
2166 LocMsg(),
2167 mApi(api),
2168 mContext(context),
2169 mBlockCPI(blockCPIInfo),
2170 mLatitude(latitude),
2171 mLongitude(longitude),
2172 mAccuracy(accuracy) {}
2173 inline virtual void proc() const {
2174 if ((uptimeMillis() <= mBlockCPI.blockedTillTsMs) &&
2175 (fabs(mLatitude-mBlockCPI.latitude) <= mBlockCPI.latLonDiffThreshold) &&
2176 (fabs(mLongitude-mBlockCPI.longitude) <= mBlockCPI.latLonDiffThreshold)) {
2177
2178 LOC_LOGD("%s]: positon injeciton blocked: lat: %f, lon: %f, accuracy: %f",
2179 __func__, mLatitude, mLongitude, mAccuracy);
2180
2181 } else {
2182 mApi.injectPosition(mLatitude, mLongitude, mAccuracy);
2183 }
2184 }
2185 };
2186
2187 sendMsg(new MsgInjectLocation(*mLocApi, *mContext, mBlockCPIInfo,
2188 latitude, longitude, accuracy));
2189 }
2190
2191 void
injectLocationExtCommand(const GnssLocationInfoNotification & locationInfo)2192 GnssAdapter::injectLocationExtCommand(const GnssLocationInfoNotification &locationInfo)
2193 {
2194 LOC_LOGd("latitude %8.4f longitude %8.4f accuracy %8.4f, tech mask 0x%x",
2195 locationInfo.location.latitude, locationInfo.location.longitude,
2196 locationInfo.location.accuracy, locationInfo.location.techMask);
2197
2198 struct MsgInjectLocationExt : public LocMsg {
2199 LocApiBase& mApi;
2200 ContextBase& mContext;
2201 GnssLocationInfoNotification mLocationInfo;
2202 inline MsgInjectLocationExt(LocApiBase& api,
2203 ContextBase& context,
2204 GnssLocationInfoNotification locationInfo) :
2205 LocMsg(),
2206 mApi(api),
2207 mContext(context),
2208 mLocationInfo(locationInfo) {}
2209 inline virtual void proc() const {
2210 // false to indicate for none-ODCPI
2211 mApi.injectPosition(mLocationInfo, false);
2212 }
2213 };
2214
2215 sendMsg(new MsgInjectLocationExt(*mLocApi, *mContext, locationInfo));
2216 }
2217
2218 void
injectTimeCommand(int64_t time,int64_t timeReference,int32_t uncertainty)2219 GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
2220 {
2221 LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
2222 __func__, (long long)time, (long long)timeReference, uncertainty);
2223
2224 struct MsgInjectTime : public LocMsg {
2225 LocApiBase& mApi;
2226 ContextBase& mContext;
2227 int64_t mTime;
2228 int64_t mTimeReference;
2229 int32_t mUncertainty;
2230 inline MsgInjectTime(LocApiBase& api,
2231 ContextBase& context,
2232 int64_t time,
2233 int64_t timeReference,
2234 int32_t uncertainty) :
2235 LocMsg(),
2236 mApi(api),
2237 mContext(context),
2238 mTime(time),
2239 mTimeReference(timeReference),
2240 mUncertainty(uncertainty) {}
2241 inline virtual void proc() const {
2242 mApi.setTime(mTime, mTimeReference, mUncertainty);
2243 }
2244 };
2245
2246 sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
2247 }
2248
2249 // This command is to called to block the position to be injected to the modem.
2250 // This can happen for network position that comes from modem.
2251 void
blockCPICommand(double latitude,double longitude,float accuracy,int blockDurationMsec,double latLonDiffThreshold)2252 GnssAdapter::blockCPICommand(double latitude, double longitude,
2253 float accuracy, int blockDurationMsec,
2254 double latLonDiffThreshold)
2255 {
2256 struct MsgBlockCPI : public LocMsg {
2257 BlockCPIInfo& mDstCPIInfo;
2258 BlockCPIInfo mSrcCPIInfo;
2259
2260 inline MsgBlockCPI(BlockCPIInfo& dstCPIInfo,
2261 BlockCPIInfo& srcCPIInfo) :
2262 mDstCPIInfo(dstCPIInfo),
2263 mSrcCPIInfo(srcCPIInfo) {}
2264 inline virtual void proc() const {
2265 // in the same hal thread, save the cpi to be blocked
2266 // the global variable
2267 mDstCPIInfo = mSrcCPIInfo;
2268 }
2269 };
2270
2271 // construct the new block CPI info and queue on the same thread
2272 // for processing
2273 BlockCPIInfo blockCPIInfo;
2274 blockCPIInfo.latitude = latitude;
2275 blockCPIInfo.longitude = longitude;
2276 blockCPIInfo.accuracy = accuracy;
2277 blockCPIInfo.blockedTillTsMs = uptimeMillis() + blockDurationMsec;
2278 blockCPIInfo.latLonDiffThreshold = latLonDiffThreshold;
2279
2280 LOC_LOGD("%s]: block CPI lat: %f, lon: %f ", __func__, latitude, longitude);
2281 // send a message to record down the coarse position
2282 // to be blocked from injection in the master copy (mBlockCPIInfo)
2283 sendMsg(new MsgBlockCPI(mBlockCPIInfo, blockCPIInfo));
2284 }
2285
2286 void
updateSystemPowerState(PowerStateType systemPowerState)2287 GnssAdapter::updateSystemPowerState(PowerStateType systemPowerState) {
2288 if (POWER_STATE_UNKNOWN != systemPowerState) {
2289 mSystemPowerState = systemPowerState;
2290 mLocApi->updateSystemPowerState(mSystemPowerState);
2291 }
2292 }
2293
2294 void
updateSystemPowerStateCommand(PowerStateType systemPowerState)2295 GnssAdapter::updateSystemPowerStateCommand(PowerStateType systemPowerState) {
2296 LOC_LOGd("power event %d", systemPowerState);
2297
2298 struct MsgUpdatePowerState : public LocMsg {
2299 GnssAdapter& mAdapter;
2300 PowerStateType mSystemPowerState;
2301
2302 inline MsgUpdatePowerState(GnssAdapter& adapter,
2303 PowerStateType systemPowerState) :
2304 LocMsg(),
2305 mAdapter(adapter),
2306 mSystemPowerState(systemPowerState) {}
2307 inline virtual void proc() const {
2308 mAdapter.updateSystemPowerState(mSystemPowerState);
2309 }
2310 };
2311
2312 sendMsg(new MsgUpdatePowerState(*this, systemPowerState));
2313 }
2314
2315 void
addClientCommand(LocationAPI * client,const LocationCallbacks & callbacks)2316 GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
2317 {
2318 LOC_LOGD("%s]: client %p", __func__, client);
2319
2320 struct MsgAddClient : public LocMsg {
2321 GnssAdapter& mAdapter;
2322 LocationAPI* mClient;
2323 const LocationCallbacks mCallbacks;
2324 inline MsgAddClient(GnssAdapter& adapter,
2325 LocationAPI* client,
2326 const LocationCallbacks& callbacks) :
2327 LocMsg(),
2328 mAdapter(adapter),
2329 mClient(client),
2330 mCallbacks(callbacks) {}
2331 inline virtual void proc() const {
2332 // check whether we need to notify client of cached location system info
2333 mAdapter.notifyClientOfCachedLocationSystemInfo(mClient, mCallbacks);
2334 mAdapter.saveClient(mClient, mCallbacks);
2335 }
2336 };
2337
2338 sendMsg(new MsgAddClient(*this, client, callbacks));
2339 }
2340
2341 void
stopClientSessions(LocationAPI * client)2342 GnssAdapter::stopClientSessions(LocationAPI* client)
2343 {
2344 LOC_LOGD("%s]: client %p", __func__, client);
2345
2346 /* Time-based Tracking */
2347 std::vector<LocationSessionKey> vTimeBasedTrackingClient;
2348 for (auto it : mTimeBasedTrackingSessions) {
2349 if (client == it.first.client) {
2350 vTimeBasedTrackingClient.emplace_back(it.first.client, it.first.id);
2351 }
2352 }
2353 for (auto key : vTimeBasedTrackingClient) {
2354 stopTimeBasedTrackingMultiplex(key.client, key.id);
2355 eraseTrackingSession(key.client, key.id);
2356 }
2357
2358 /* Distance-based Tracking */
2359 for (auto it = mDistanceBasedTrackingSessions.begin();
2360 it != mDistanceBasedTrackingSessions.end(); /* no increment here*/) {
2361 if (client == it->first.client) {
2362 mLocApi->stopDistanceBasedTracking(it->first.id, new LocApiResponse(*getContext(),
2363 [this, client, id=it->first.id] (LocationError err) {
2364 if (LOCATION_ERROR_SUCCESS == err) {
2365 eraseTrackingSession(client, id);
2366 }
2367 }
2368 ));
2369 }
2370 ++it; // increment only when not erasing an iterator
2371 }
2372
2373 }
2374
2375 void
updateClientsEventMask()2376 GnssAdapter::updateClientsEventMask()
2377 {
2378 LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
2379 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2380 if (it->second.trackingCb != nullptr ||
2381 it->second.gnssLocationInfoCb != nullptr ||
2382 it->second.engineLocationsInfoCb != nullptr) {
2383 mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
2384 }
2385 if (it->second.gnssSvCb != nullptr) {
2386 mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
2387 }
2388 if ((it->second.gnssNmeaCb != nullptr) && (mNmeaMask)) {
2389 mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
2390 }
2391 if (it->second.gnssMeasurementsCb != nullptr) {
2392 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
2393 }
2394 if (it->second.gnssDataCb != nullptr) {
2395 mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
2396 mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
2397 updateNmeaMask(mNmeaMask | LOC_NMEA_MASK_DEBUG_V02);
2398 }
2399 }
2400
2401 /*
2402 ** For Automotive use cases we need to enable MEASUREMENT, POLY and EPHEMERIS
2403 ** when QDR is enabled (e.g.: either enabled via conf file or
2404 ** engine hub is loaded successfully).
2405 ** Note: this need to be called from msg queue thread.
2406 */
2407 if((1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) ||
2408 (true == initEngHubProxy())) {
2409 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
2410 mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT;
2411 mask |= LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT;
2412 mask |= LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT;
2413 mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO;
2414 mask |= LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO;
2415
2416 // Nhz measurement bit is set based on callback from loc eng hub
2417 // for Nhz engines.
2418 mask |= checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT);
2419
2420 LOC_LOGd("Auto usecase, Enable MEAS/POLY/EPHEMERIS - mask 0x%" PRIx64 "",
2421 mask);
2422 }
2423
2424 if (mAgpsManager.isRegistered()) {
2425 mask |= LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST;
2426 }
2427 // Add ODCPI handling
2428 if (nullptr != mOdcpiRequestCb) {
2429 mask |= LOC_API_ADAPTER_BIT_REQUEST_WIFI;
2430 }
2431
2432 // need to register for leap second info
2433 // for proper nmea generation
2434 mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO;
2435
2436 // always register for NI NOTIFY VERIFY to handle internally in HAL
2437 mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
2438
2439 updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
2440 }
2441
2442 void
handleEngineUpEvent()2443 GnssAdapter::handleEngineUpEvent()
2444 {
2445 LOC_LOGD("%s]: ", __func__);
2446
2447 struct MsgHandleEngineUpEvent : public LocMsg {
2448 GnssAdapter& mAdapter;
2449 inline MsgHandleEngineUpEvent(GnssAdapter& adapter) :
2450 LocMsg(),
2451 mAdapter(adapter) {}
2452 virtual void proc() const {
2453 mAdapter.setEngineCapabilitiesKnown(true);
2454 mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
2455 // must be called only after capabilities are known
2456 mAdapter.setConfig();
2457 mAdapter.gnssSvIdConfigUpdate();
2458 mAdapter.gnssSvTypeConfigUpdate();
2459 mAdapter.updateSystemPowerState(mAdapter.getSystemPowerState());
2460 // restart sessions
2461 mAdapter.restartSessions(true);
2462 for (auto msg: mAdapter.mPendingMsgs) {
2463 mAdapter.sendMsg(msg);
2464 }
2465 mAdapter.mPendingMsgs.clear();
2466 }
2467 };
2468
2469 readConfigCommand();
2470 sendMsg(new MsgHandleEngineUpEvent(*this));
2471 }
2472
2473 void
restartSessions(bool modemSSR)2474 GnssAdapter::restartSessions(bool modemSSR)
2475 {
2476 LOC_LOGi(":enter");
2477
2478 if (modemSSR) {
2479 // odcpi session is no longer active after restart
2480 mOdcpiRequestActive = false;
2481 }
2482
2483 // SPE will be restarted now, so set this variable to false.
2484 mSPEAlreadyRunningAtHighestInterval = false;
2485
2486 checkAndRestartSPESession();
2487 }
2488
checkAndRestartSPESession()2489 void GnssAdapter::checkAndRestartSPESession()
2490 {
2491 LOC_LOGD("%s]: ", __func__);
2492
2493 // SPE will be restarted now, so set this variable to false.
2494 mSPEAlreadyRunningAtHighestInterval = false;
2495
2496 checkAndRestartTimeBasedSession();
2497
2498 for (auto it = mDistanceBasedTrackingSessions.begin();
2499 it != mDistanceBasedTrackingSessions.end(); ++it) {
2500 mLocApi->startDistanceBasedTracking(it->first.id, it->second,
2501 new LocApiResponse(*getContext(),
2502 [] (LocationError /*err*/) {}));
2503 }
2504 }
2505
2506 // suspend all on-going sessions
2507 void
suspendSessions()2508 GnssAdapter::suspendSessions()
2509 {
2510 LOC_LOGi(":enter");
2511
2512 if (!mTimeBasedTrackingSessions.empty()) {
2513 // inform engine hub that GNSS session has stopped
2514 mEngHubProxy->gnssStopFix();
2515 mLocApi->stopFix(nullptr);
2516 mSPEAlreadyRunningAtHighestInterval = false;
2517 }
2518 }
2519
checkAndRestartTimeBasedSession()2520 void GnssAdapter::checkAndRestartTimeBasedSession()
2521 {
2522 LOC_LOGD("%s]: ", __func__);
2523
2524 if (!mTimeBasedTrackingSessions.empty()) {
2525 // get the LocationOptions that has the smallest interval, which should be the active one
2526 TrackingOptions smallestIntervalOptions; // size is zero until set for the first time
2527 TrackingOptions highestPowerTrackingOptions;
2528 memset(&smallestIntervalOptions, 0, sizeof(smallestIntervalOptions));
2529 memset(&highestPowerTrackingOptions, 0, sizeof(highestPowerTrackingOptions));
2530 for (auto it = mTimeBasedTrackingSessions.begin();
2531 it != mTimeBasedTrackingSessions.end(); ++it) {
2532 // size of zero means we havent set it yet
2533 if (0 == smallestIntervalOptions.size ||
2534 it->second.minInterval < smallestIntervalOptions.minInterval) {
2535 smallestIntervalOptions = it->second;
2536 }
2537 GnssPowerMode powerMode = it->second.powerMode;
2538 // Size of zero means we havent set it yet
2539 if (0 == highestPowerTrackingOptions.size ||
2540 (GNSS_POWER_MODE_INVALID != powerMode &&
2541 powerMode < highestPowerTrackingOptions.powerMode)) {
2542 highestPowerTrackingOptions = it->second;
2543 }
2544 }
2545
2546 highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
2547 // want to run SPE session at a fixed min interval in some automotive scenarios
2548 if(!checkAndSetSPEToRunforNHz(highestPowerTrackingOptions)) {
2549 mLocApi->startTimeBasedTracking(highestPowerTrackingOptions, nullptr);
2550 }
2551 }
2552 }
2553
2554 void
notifyClientOfCachedLocationSystemInfo(LocationAPI * client,const LocationCallbacks & callbacks)2555 GnssAdapter::notifyClientOfCachedLocationSystemInfo(
2556 LocationAPI* client, const LocationCallbacks& callbacks) {
2557
2558 if (mLocSystemInfo.systemInfoMask) {
2559 // client need to be notified if client has not yet previously registered
2560 // for the info but now register for it.
2561 bool notifyClientOfSystemInfo = false;
2562 // check whether we need to notify client of cached location system info
2563 //
2564 // client need to be notified if client has not yet previously registered
2565 // for the info but now register for it.
2566 if (callbacks.locationSystemInfoCb) {
2567 notifyClientOfSystemInfo = true;
2568 auto it = mClientData.find(client);
2569 if (it != mClientData.end()) {
2570 LocationCallbacks oldCallbacks = it->second;
2571 if (oldCallbacks.locationSystemInfoCb) {
2572 notifyClientOfSystemInfo = false;
2573 }
2574 }
2575 }
2576
2577 if (notifyClientOfSystemInfo) {
2578 callbacks.locationSystemInfoCb(mLocSystemInfo);
2579 }
2580 }
2581 }
2582
2583 bool
isTimeBasedTrackingSession(LocationAPI * client,uint32_t sessionId)2584 GnssAdapter::isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
2585 {
2586 LocationSessionKey key(client, sessionId);
2587 return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
2588 }
2589
2590 bool
isDistanceBasedTrackingSession(LocationAPI * client,uint32_t sessionId)2591 GnssAdapter::isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
2592 {
2593 LocationSessionKey key(client, sessionId);
2594 return (mDistanceBasedTrackingSessions.find(key) != mDistanceBasedTrackingSessions.end());
2595 }
2596
2597 bool
hasCallbacksToStartTracking(LocationAPI * client)2598 GnssAdapter::hasCallbacksToStartTracking(LocationAPI* client)
2599 {
2600 bool allowed = false;
2601 auto it = mClientData.find(client);
2602 if (it != mClientData.end()) {
2603 if (it->second.trackingCb || it->second.gnssLocationInfoCb ||
2604 it->second.engineLocationsInfoCb || it->second.gnssMeasurementsCb) {
2605 allowed = true;
2606 } else {
2607 LOC_LOGi("missing right callback to start tracking")
2608 }
2609 } else {
2610 LOC_LOGi("client %p not found", client)
2611 }
2612 return allowed;
2613 }
2614
2615 bool
isTrackingSession(LocationAPI * client,uint32_t sessionId)2616 GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
2617 {
2618 LocationSessionKey key(client, sessionId);
2619 return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
2620 }
2621
2622 void
reportPowerStateIfChanged()2623 GnssAdapter::reportPowerStateIfChanged()
2624 {
2625 bool newPowerOn = !mTimeBasedTrackingSessions.empty() ||
2626 !mDistanceBasedTrackingSessions.empty();
2627 if (newPowerOn != mPowerOn) {
2628 mPowerOn = newPowerOn;
2629 if (mPowerStateCb != nullptr) {
2630 mPowerStateCb(mPowerOn);
2631 }
2632 }
2633 }
2634
2635 void
getPowerStateChangesCommand(void * powerStateCb)2636 GnssAdapter::getPowerStateChangesCommand(void* powerStateCb)
2637 {
2638 LOC_LOGD("%s]: ", __func__);
2639
2640 struct MsgReportLocation : public LocMsg {
2641 GnssAdapter& mAdapter;
2642 powerStateCallback mPowerStateCb;
2643 inline MsgReportLocation(GnssAdapter& adapter,
2644 powerStateCallback powerStateCb) :
2645 LocMsg(),
2646 mAdapter(adapter),
2647 mPowerStateCb(powerStateCb) {}
2648 inline virtual void proc() const {
2649 mAdapter.savePowerStateCallback(mPowerStateCb);
2650 mPowerStateCb(mAdapter.getPowerState());
2651 }
2652 };
2653
2654 sendMsg(new MsgReportLocation(*this, (powerStateCallback)powerStateCb));
2655 }
2656
2657 void
saveTrackingSession(LocationAPI * client,uint32_t sessionId,const TrackingOptions & options)2658 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
2659 const TrackingOptions& options)
2660 {
2661 LocationSessionKey key(client, sessionId);
2662 if ((options.minDistance > 0) &&
2663 ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
2664 mDistanceBasedTrackingSessions[key] = options;
2665 } else {
2666 mTimeBasedTrackingSessions[key] = options;
2667 }
2668 reportPowerStateIfChanged();
2669 }
2670
2671 void
eraseTrackingSession(LocationAPI * client,uint32_t sessionId)2672 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
2673 {
2674 LocationSessionKey key(client, sessionId);
2675 auto it = mTimeBasedTrackingSessions.find(key);
2676 if (it != mTimeBasedTrackingSessions.end()) {
2677 mTimeBasedTrackingSessions.erase(it);
2678 } else {
2679 auto itr = mDistanceBasedTrackingSessions.find(key);
2680 if (itr != mDistanceBasedTrackingSessions.end()) {
2681 mDistanceBasedTrackingSessions.erase(itr);
2682 }
2683 }
2684 reportPowerStateIfChanged();
2685 }
2686
2687
setLocPositionMode(const LocPosMode & mode)2688 bool GnssAdapter::setLocPositionMode(const LocPosMode& mode) {
2689 if (!mLocPositionMode.equals(mode)) {
2690 mLocPositionMode = mode;
2691 return true;
2692 } else {
2693 return false;
2694 }
2695 }
2696
2697 void
reportResponse(LocationAPI * client,LocationError err,uint32_t sessionId)2698 GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
2699 {
2700 LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
2701
2702 auto it = mClientData.find(client);
2703 if (it != mClientData.end() && it->second.responseCb != nullptr) {
2704 it->second.responseCb(err, sessionId);
2705 } else {
2706 LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
2707 }
2708 }
2709
2710 void
reportResponse(LocationError err,uint32_t sessionId)2711 GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
2712 {
2713 LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
2714
2715 if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
2716 mControlCallbacks.responseCb(err, sessionId);
2717 } else {
2718 LOC_LOGW("%s]: control client response callback not found", __func__);
2719 }
2720 }
2721
2722 void
reportResponse(size_t count,LocationError * errs,uint32_t * ids)2723 GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
2724 {
2725 IF_LOC_LOGD {
2726 std::string idsString = "[";
2727 std::string errsString = "[";
2728 if (NULL != ids && NULL != errs) {
2729 for (size_t i=0; i < count; ++i) {
2730 idsString += std::to_string(ids[i]) + " ";
2731 errsString += std::to_string(errs[i]) + " ";
2732 }
2733 }
2734 idsString += "]";
2735 errsString += "]";
2736
2737 LOC_LOGD("%s]: ids %s errs %s",
2738 __func__, idsString.c_str(), errsString.c_str());
2739 }
2740
2741 if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
2742 mControlCallbacks.collectiveResponseCb(count, errs, ids);
2743 } else {
2744 LOC_LOGW("%s]: control client callback not found", __func__);
2745 }
2746 }
2747
2748 uint32_t
startTrackingCommand(LocationAPI * client,TrackingOptions & options)2749 GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options)
2750 {
2751 uint32_t sessionId = generateSessionId();
2752 LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u powermode %u tbm %u",
2753 __func__, client, sessionId, options.minInterval, options.minDistance, options.mode,
2754 options.powerMode, options.tbm);
2755
2756 struct MsgStartTracking : public LocMsg {
2757 GnssAdapter& mAdapter;
2758 LocApiBase& mApi;
2759 LocationAPI* mClient;
2760 uint32_t mSessionId;
2761 mutable TrackingOptions mOptions;
2762 inline MsgStartTracking(GnssAdapter& adapter,
2763 LocApiBase& api,
2764 LocationAPI* client,
2765 uint32_t sessionId,
2766 TrackingOptions options) :
2767 LocMsg(),
2768 mAdapter(adapter),
2769 mApi(api),
2770 mClient(client),
2771 mSessionId(sessionId),
2772 mOptions(options) {}
2773 inline virtual void proc() const {
2774 // distance based tracking will need to know engine capabilities before it can start
2775 if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
2776 mAdapter.mPendingMsgs.push_back(new MsgStartTracking(*this));
2777 return;
2778 }
2779 LocationError err = LOCATION_ERROR_SUCCESS;
2780 if (!mAdapter.hasCallbacksToStartTracking(mClient)) {
2781 err = LOCATION_ERROR_CALLBACK_MISSING;
2782 } else if (0 == mOptions.size) {
2783 err = LOCATION_ERROR_INVALID_PARAMETER;
2784 } else {
2785 if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
2786 mOptions.minInterval = MIN_TRACKING_INTERVAL;
2787 }
2788 if (mOptions.minDistance > 0 &&
2789 ContextBase::isMessageSupported(
2790 LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
2791 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2792 mApi.startDistanceBasedTracking(mSessionId, mOptions,
2793 new LocApiResponse(*mAdapter.getContext(),
2794 [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
2795 (LocationError err) {
2796 if (LOCATION_ERROR_SUCCESS != err) {
2797 mAdapter.eraseTrackingSession(mClient, mSessionId);
2798 }
2799 mAdapter.reportResponse(mClient, err, mSessionId);
2800 }));
2801 } else {
2802 if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
2803 mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2804 LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2805 mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2806 mOptions.powerMode = GNSS_POWER_MODE_M2;
2807 }
2808 // Api doesn't support multiple clients for time based tracking, so mutiplex
2809 bool reportToClientWithNoWait =
2810 mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId, mOptions);
2811 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2812
2813 if (reportToClientWithNoWait) {
2814 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
2815 }
2816 }
2817 }
2818 }
2819 };
2820
2821 sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
2822 return sessionId;
2823
2824 }
2825
2826 bool
startTimeBasedTrackingMultiplex(LocationAPI * client,uint32_t sessionId,const TrackingOptions & options)2827 GnssAdapter::startTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t sessionId,
2828 const TrackingOptions& options)
2829 {
2830 bool reportToClientWithNoWait = true;
2831
2832 if (mTimeBasedTrackingSessions.empty()) {
2833 /*Reset previous NMEA reported time stamp */
2834 mPrevNmeaRptTimeNsec = 0;
2835 startTimeBasedTracking(client, sessionId, options);
2836 // need to wait for QMI callback
2837 reportToClientWithNoWait = false;
2838 } else {
2839 // find the smallest interval and powerMode
2840 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2841 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2842 memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
2843 for (auto it = mTimeBasedTrackingSessions.begin(); it != mTimeBasedTrackingSessions.end(); ++it) {
2844 // if not set or there is a new smallest interval, then set the new interval
2845 if (0 == multiplexedOptions.size ||
2846 it->second.minInterval < multiplexedOptions.minInterval) {
2847 multiplexedOptions = it->second;
2848 }
2849 // if session is not the one we are updating and either powerMode
2850 // is not set or there is a new smallest powerMode, then set the new powerMode
2851 if (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2852 it->second.powerMode < multiplexedPowerMode) {
2853 multiplexedPowerMode = it->second.powerMode;
2854 }
2855 }
2856 bool updateOptions = false;
2857 // if session we are starting has smaller interval then next smallest
2858 if (options.minInterval < multiplexedOptions.minInterval) {
2859 multiplexedOptions.minInterval = options.minInterval;
2860 updateOptions = true;
2861 }
2862
2863 // if session we are starting has smaller powerMode then next smallest
2864 if (options.powerMode < multiplexedPowerMode) {
2865 multiplexedOptions.powerMode = options.powerMode;
2866 updateOptions = true;
2867 }
2868 if (updateOptions) {
2869 // restart time based tracking with the newly updated options
2870
2871 startTimeBasedTracking(client, sessionId, multiplexedOptions);
2872 // need to wait for QMI callback
2873 reportToClientWithNoWait = false;
2874 }
2875 // else part: no QMI call is made, need to report back to client right away
2876 }
2877
2878 return reportToClientWithNoWait;
2879 }
2880
2881 void
startTimeBasedTracking(LocationAPI * client,uint32_t sessionId,const TrackingOptions & trackingOptions)2882 GnssAdapter::startTimeBasedTracking(LocationAPI* client, uint32_t sessionId,
2883 const TrackingOptions& trackingOptions)
2884 {
2885 LOC_LOGd("minInterval %u minDistance %u mode %u powermode %u tbm %u",
2886 trackingOptions.minInterval, trackingOptions.minDistance,
2887 trackingOptions.mode, trackingOptions.powerMode, trackingOptions.tbm);
2888
2889 LocPosMode locPosMode = {};
2890 convertOptions(locPosMode, trackingOptions);
2891 //Update Position mode parameters
2892 setLocPositionMode(locPosMode);
2893 // inform engine hub that GNSS session is about to start
2894 mEngHubProxy->gnssSetFixMode(locPosMode);
2895 mEngHubProxy->gnssStartFix();
2896
2897 // want to run SPE session at a fixed min interval in some automotive scenarios
2898 // use a local copy of TrackingOptions as the TBF may get modified in the
2899 // checkAndSetSPEToRunforNHz function
2900 TrackingOptions tempOptions(trackingOptions);
2901 if (!checkAndSetSPEToRunforNHz(tempOptions)) {
2902 mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(),
2903 [this, client, sessionId] (LocationError err) {
2904 if (LOCATION_ERROR_SUCCESS != err) {
2905 eraseTrackingSession(client, sessionId);
2906 }
2907
2908 reportResponse(client, err, sessionId);
2909 }
2910 ));
2911 } else {
2912 reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId);
2913 }
2914
2915 }
2916
2917 void
updateTracking(LocationAPI * client,uint32_t sessionId,const TrackingOptions & updatedOptions,const TrackingOptions & oldOptions)2918 GnssAdapter::updateTracking(LocationAPI* client, uint32_t sessionId,
2919 const TrackingOptions& updatedOptions, const TrackingOptions& oldOptions)
2920 {
2921 LocPosMode locPosMode = {};
2922 convertOptions(locPosMode, updatedOptions);
2923
2924 // inform engine hub that GNSS session is about to start
2925 mEngHubProxy->gnssSetFixMode(locPosMode);
2926 mEngHubProxy->gnssStartFix();
2927
2928 // want to run SPE session at a fixed min interval in some automotive scenarios
2929 // use a local copy of TrackingOptions as the TBF may get modified in the
2930 // checkAndSetSPEToRunforNHz function
2931 TrackingOptions tempOptions(updatedOptions);
2932 if(!checkAndSetSPEToRunforNHz(tempOptions)) {
2933 mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(),
2934 [this, client, sessionId, oldOptions] (LocationError err) {
2935 if (LOCATION_ERROR_SUCCESS != err) {
2936 // restore the old LocationOptions
2937 saveTrackingSession(client, sessionId, oldOptions);
2938 }
2939 reportResponse(client, err, sessionId);
2940 }
2941 ));
2942 } else {
2943 reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId);
2944 }
2945 }
2946
2947 void
updateTrackingOptionsCommand(LocationAPI * client,uint32_t id,TrackingOptions & options)2948 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
2949 TrackingOptions& options)
2950 {
2951 LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
2952 __func__, client, id, options.minInterval, options.mode);
2953
2954 struct MsgUpdateTracking : public LocMsg {
2955 GnssAdapter& mAdapter;
2956 LocApiBase& mApi;
2957 LocationAPI* mClient;
2958 uint32_t mSessionId;
2959 mutable TrackingOptions mOptions;
2960 inline MsgUpdateTracking(GnssAdapter& adapter,
2961 LocApiBase& api,
2962 LocationAPI* client,
2963 uint32_t sessionId,
2964 TrackingOptions options) :
2965 LocMsg(),
2966 mAdapter(adapter),
2967 mApi(api),
2968 mClient(client),
2969 mSessionId(sessionId),
2970 mOptions(options) {}
2971 inline virtual void proc() const {
2972 // distance based tracking will need to know engine capabilities before it can start
2973 if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
2974 mAdapter.mPendingMsgs.push_back(new MsgUpdateTracking(*this));
2975 return;
2976 }
2977 LocationError err = LOCATION_ERROR_SUCCESS;
2978 bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
2979 bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
2980 if (!isTimeBased && !isDistanceBased) {
2981 err = LOCATION_ERROR_ID_UNKNOWN;
2982 } else if (0 == mOptions.size) {
2983 err = LOCATION_ERROR_INVALID_PARAMETER;
2984 }
2985 if (LOCATION_ERROR_SUCCESS != err) {
2986 mAdapter.reportResponse(mClient, err, mSessionId);
2987 } else {
2988 if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
2989 mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2990 LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2991 mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2992 mOptions.powerMode = GNSS_POWER_MODE_M2;
2993 }
2994 if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
2995 mOptions.minInterval = MIN_TRACKING_INTERVAL;
2996 }
2997 // Now update session as required
2998 if (isTimeBased && mOptions.minDistance > 0) {
2999 // switch from time based to distance based
3000 // Api doesn't support multiple clients for time based tracking, so mutiplex
3001 bool reportToClientWithNoWait =
3002 mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
3003 // erases the time based Session
3004 mAdapter.eraseTrackingSession(mClient, mSessionId);
3005 if (reportToClientWithNoWait) {
3006 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
3007 }
3008 // saves as distance based Session
3009 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3010 mApi.startDistanceBasedTracking(mSessionId, mOptions,
3011 new LocApiResponse(*mAdapter.getContext(),
3012 [] (LocationError /*err*/) {}));
3013 } else if (isDistanceBased && mOptions.minDistance == 0) {
3014 // switch from distance based to time based
3015 mAdapter.eraseTrackingSession(mClient, mSessionId);
3016 mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
3017 *mAdapter.getContext(),
3018 [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
3019 mClient = mClient] (LocationError /*err*/) {
3020 // Api doesn't support multiple clients for time based tracking,
3021 // so mutiplex
3022 bool reportToClientWithNoWait =
3023 mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId,
3024 mOptions);
3025 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3026
3027 if (reportToClientWithNoWait) {
3028 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
3029 }
3030 }));
3031 } else if (isTimeBased) {
3032 // update time based tracking
3033 // Api doesn't support multiple clients for time based tracking, so mutiplex
3034 bool reportToClientWithNoWait =
3035 mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions);
3036 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3037
3038 if (reportToClientWithNoWait) {
3039 mAdapter.reportResponse(mClient, err, mSessionId);
3040 }
3041 } else if (isDistanceBased) {
3042 // restart distance based tracking
3043 mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
3044 *mAdapter.getContext(),
3045 [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
3046 mClient = mClient, &mApi = mApi] (LocationError err) {
3047 if (LOCATION_ERROR_SUCCESS == err) {
3048 mApi.startDistanceBasedTracking(mSessionId, mOptions,
3049 new LocApiResponse(*mAdapter.getContext(),
3050 [&mAdapter, mClient, mSessionId, mOptions]
3051 (LocationError err) {
3052 if (LOCATION_ERROR_SUCCESS == err) {
3053 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3054 }
3055 mAdapter.reportResponse(mClient, err, mSessionId);
3056 }));
3057 }
3058 }));
3059 }
3060 }
3061 }
3062 };
3063
3064 sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
3065 }
3066
3067 bool
updateTrackingMultiplex(LocationAPI * client,uint32_t id,const TrackingOptions & trackingOptions)3068 GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
3069 const TrackingOptions& trackingOptions)
3070 {
3071 bool reportToClientWithNoWait = true;
3072
3073 LocationSessionKey key(client, id);
3074 // get the session we are updating
3075 auto it = mTimeBasedTrackingSessions.find(key);
3076
3077 // cache the clients existing LocationOptions
3078 TrackingOptions oldOptions = it->second;
3079
3080 // if session we are updating exists and the minInterval or powerMode has changed
3081 if (it != mTimeBasedTrackingSessions.end() &&
3082 (it->second.minInterval != trackingOptions.minInterval ||
3083 it->second.powerMode != trackingOptions.powerMode)) {
3084 // find the smallest interval and powerMode, other than the session we are updating
3085 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
3086 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
3087 memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
3088 for (auto it2 = mTimeBasedTrackingSessions.begin();
3089 it2 != mTimeBasedTrackingSessions.end(); ++it2) {
3090 // if session is not the one we are updating and either interval
3091 // is not set or there is a new smallest interval, then set the new interval
3092 if (it2->first != key && (0 == multiplexedOptions.size ||
3093 it2->second.minInterval < multiplexedOptions.minInterval)) {
3094 multiplexedOptions = it2->second;
3095 }
3096 // if session is not the one we are updating and either powerMode
3097 // is not set or there is a new smallest powerMode, then set the new powerMode
3098 if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
3099 it2->second.powerMode < multiplexedPowerMode)) {
3100 multiplexedPowerMode = it2->second.powerMode;
3101 }
3102 // else part: no QMI call is made, need to report back to client right away
3103 }
3104 bool updateOptions = false;
3105 // if session we are updating has smaller interval then next smallest
3106 if (trackingOptions.minInterval < multiplexedOptions.minInterval) {
3107 multiplexedOptions.minInterval = trackingOptions.minInterval;
3108 updateOptions = true;
3109 }
3110 // if session we are updating has smaller powerMode then next smallest
3111 if (trackingOptions.powerMode < multiplexedPowerMode) {
3112 multiplexedOptions.powerMode = trackingOptions.powerMode;
3113 updateOptions = true;
3114 }
3115 // if only one session exists, then tracking should be updated with it
3116 if (1 == mTimeBasedTrackingSessions.size()) {
3117 multiplexedOptions = trackingOptions;
3118 updateOptions = true;
3119 }
3120 if (updateOptions) {
3121 // restart time based tracking with the newly updated options
3122 updateTracking(client, id, multiplexedOptions, oldOptions);
3123 // need to wait for QMI callback
3124 reportToClientWithNoWait = false;
3125 }
3126 }
3127
3128 return reportToClientWithNoWait;
3129 }
3130
3131 void
stopTrackingCommand(LocationAPI * client,uint32_t id)3132 GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
3133 {
3134 LOC_LOGD("%s]: client %p id %u", __func__, client, id);
3135
3136 struct MsgStopTracking : public LocMsg {
3137 GnssAdapter& mAdapter;
3138 LocApiBase& mApi;
3139 LocationAPI* mClient;
3140 uint32_t mSessionId;
3141 inline MsgStopTracking(GnssAdapter& adapter,
3142 LocApiBase& api,
3143 LocationAPI* client,
3144 uint32_t sessionId) :
3145 LocMsg(),
3146 mAdapter(adapter),
3147 mApi(api),
3148 mClient(client),
3149 mSessionId(sessionId) {}
3150 inline virtual void proc() const {
3151 bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
3152 bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
3153 if (isTimeBased || isDistanceBased) {
3154 if (isTimeBased) {
3155 // Api doesn't support multiple clients for time based tracking, so mutiplex
3156 bool reportToClientWithNoWait =
3157 mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
3158 mAdapter.eraseTrackingSession(mClient, mSessionId);
3159
3160 if (reportToClientWithNoWait) {
3161 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
3162 }
3163 } else if (isDistanceBased) {
3164 mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
3165 *mAdapter.getContext(),
3166 [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
3167 (LocationError err) {
3168 if (LOCATION_ERROR_SUCCESS == err) {
3169 mAdapter.eraseTrackingSession(mClient, mSessionId);
3170 }
3171 mAdapter.reportResponse(mClient, err, mSessionId);
3172 }));
3173 }
3174 } else {
3175 mAdapter.reportResponse(mClient, LOCATION_ERROR_ID_UNKNOWN, mSessionId);
3176 }
3177
3178 }
3179 };
3180
3181 sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
3182 }
3183
3184 bool
stopTimeBasedTrackingMultiplex(LocationAPI * client,uint32_t id)3185 GnssAdapter::stopTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t id)
3186 {
3187 bool reportToClientWithNoWait = true;
3188
3189 if (1 == mTimeBasedTrackingSessions.size()) {
3190 stopTracking(client, id);
3191 // need to wait for QMI callback
3192 reportToClientWithNoWait = false;
3193 } else {
3194 LocationSessionKey key(client, id);
3195
3196 // get the session we are stopping
3197 auto it = mTimeBasedTrackingSessions.find(key);
3198 if (it != mTimeBasedTrackingSessions.end()) {
3199 // find the smallest interval and powerMode, other than the session we are stopping
3200 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
3201 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
3202 memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
3203 for (auto it2 = mTimeBasedTrackingSessions.begin();
3204 it2 != mTimeBasedTrackingSessions.end(); ++it2) {
3205 // if session is not the one we are stopping and either interval
3206 // is not set or there is a new smallest interval, then set the new interval
3207 if (it2->first != key && (0 == multiplexedOptions.size ||
3208 it2->second.minInterval < multiplexedOptions.minInterval)) {
3209 multiplexedOptions = it2->second;
3210 }
3211 // if session is not the one we are stopping and either powerMode
3212 // is not set or there is a new smallest powerMode, then set the new powerMode
3213 if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
3214 it2->second.powerMode < multiplexedPowerMode)) {
3215 multiplexedPowerMode = it2->second.powerMode;
3216 }
3217 }
3218 // if session we are stopping has smaller interval then next smallest or
3219 // if session we are stopping has smaller powerMode then next smallest
3220 if (it->second.minInterval < multiplexedOptions.minInterval ||
3221 it->second.powerMode < multiplexedPowerMode) {
3222 multiplexedOptions.powerMode = multiplexedPowerMode;
3223 // restart time based tracking with the newly updated options
3224 startTimeBasedTracking(client, id, multiplexedOptions);
3225 // need to wait for QMI callback
3226 reportToClientWithNoWait = false;
3227 }
3228 // else part: no QMI call is made, need to report back to client right away
3229 }
3230 }
3231
3232 return reportToClientWithNoWait;
3233 }
3234
3235 void
stopTracking(LocationAPI * client,uint32_t id)3236 GnssAdapter::stopTracking(LocationAPI* client, uint32_t id)
3237 {
3238 // inform engine hub that GNSS session has stopped
3239 mEngHubProxy->gnssStopFix();
3240
3241 mLocApi->stopFix(new LocApiResponse(*getContext(),
3242 [this, client, id] (LocationError err) {
3243 reportResponse(client, err, id);
3244 }));
3245
3246 mSPEAlreadyRunningAtHighestInterval = false;
3247 }
3248
3249 bool
hasNiNotifyCallback(LocationAPI * client)3250 GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
3251 {
3252 auto it = mClientData.find(client);
3253 return (it != mClientData.end() && it->second.gnssNiCb);
3254 }
3255
3256 void
gnssNiResponseCommand(LocationAPI * client,uint32_t id,GnssNiResponse response)3257 GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
3258 uint32_t id,
3259 GnssNiResponse response)
3260 {
3261 LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
3262
3263 struct MsgGnssNiResponse : public LocMsg {
3264 GnssAdapter& mAdapter;
3265 LocationAPI* mClient;
3266 uint32_t mSessionId;
3267 GnssNiResponse mResponse;
3268 inline MsgGnssNiResponse(GnssAdapter& adapter,
3269 LocationAPI* client,
3270 uint32_t sessionId,
3271 GnssNiResponse response) :
3272 LocMsg(),
3273 mAdapter(adapter),
3274 mClient(client),
3275 mSessionId(sessionId),
3276 mResponse(response) {}
3277 inline virtual void proc() const {
3278 NiData& niData = mAdapter.getNiData();
3279 LocationError err = LOCATION_ERROR_SUCCESS;
3280 if (!mAdapter.hasNiNotifyCallback(mClient)) {
3281 err = LOCATION_ERROR_ID_UNKNOWN;
3282 } else {
3283 NiSession* pSession = NULL;
3284 if (mSessionId == niData.sessionEs.reqID &&
3285 NULL != niData.sessionEs.rawRequest) {
3286 pSession = &niData.sessionEs;
3287 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
3288 if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
3289 NULL != niData.session.rawRequest) {
3290 pthread_mutex_lock(&niData.session.tLock);
3291 niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
3292 niData.session.respRecvd = true;
3293 pthread_cond_signal(&niData.session.tCond);
3294 pthread_mutex_unlock(&niData.session.tLock);
3295 }
3296 } else if (mSessionId == niData.session.reqID &&
3297 NULL != niData.session.rawRequest) {
3298 pSession = &niData.session;
3299 }
3300
3301 if (pSession) {
3302 LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
3303 __func__, mResponse, mSessionId);
3304 pthread_mutex_lock(&pSession->tLock);
3305 pSession->resp = mResponse;
3306 pSession->respRecvd = true;
3307 pthread_cond_signal(&pSession->tCond);
3308 pthread_mutex_unlock(&pSession->tLock);
3309 } else {
3310 err = LOCATION_ERROR_ID_UNKNOWN;
3311 LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
3312 __func__, mSessionId);
3313 }
3314 }
3315 mAdapter.reportResponse(mClient, err, mSessionId);
3316 }
3317 };
3318
3319 sendMsg(new MsgGnssNiResponse(*this, client, id, response));
3320
3321 }
3322
3323 void
gnssNiResponseCommand(GnssNiResponse response,void * rawRequest)3324 GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
3325 {
3326 LOC_LOGD("%s]: response %u", __func__, response);
3327
3328 struct MsgGnssNiResponse : public LocMsg {
3329 GnssAdapter& mAdapter;
3330 LocApiBase& mApi;
3331 const GnssNiResponse mResponse;
3332 const void* mPayload;
3333 inline MsgGnssNiResponse(GnssAdapter& adapter,
3334 LocApiBase& api,
3335 const GnssNiResponse response,
3336 const void* rawRequest) :
3337 LocMsg(),
3338 mAdapter(adapter),
3339 mApi(api),
3340 mResponse(response),
3341 mPayload(rawRequest) {}
3342 inline virtual ~MsgGnssNiResponse() {
3343 }
3344 inline virtual void proc() const {
3345 mApi.informNiResponse(mResponse, mPayload);
3346 }
3347 };
3348
3349 sendMsg(new MsgGnssNiResponse(*this, *mLocApi, response, rawRequest));
3350
3351 }
3352
3353 uint32_t
enableCommand(LocationTechnologyType techType)3354 GnssAdapter::enableCommand(LocationTechnologyType techType)
3355 {
3356 uint32_t sessionId = generateSessionId();
3357 LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
3358
3359 struct MsgEnableGnss : public LocMsg {
3360 GnssAdapter& mAdapter;
3361 LocApiBase& mApi;
3362 ContextBase& mContext;
3363 uint32_t mSessionId;
3364 LocationTechnologyType mTechType;
3365 inline MsgEnableGnss(GnssAdapter& adapter,
3366 LocApiBase& api,
3367 ContextBase& context,
3368 uint32_t sessionId,
3369 LocationTechnologyType techType) :
3370 LocMsg(),
3371 mAdapter(adapter),
3372 mApi(api),
3373 mContext(context),
3374 mSessionId(sessionId),
3375 mTechType(techType) {}
3376 inline virtual void proc() const {
3377 LocationError err = LOCATION_ERROR_SUCCESS;
3378 uint32_t afwControlId = mAdapter.getAfwControlId();
3379 if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
3380 err = LOCATION_ERROR_INVALID_PARAMETER;
3381 } else if (afwControlId > 0) {
3382 err = LOCATION_ERROR_ALREADY_STARTED;
3383 } else {
3384 mContext.modemPowerVote(true);
3385 mAdapter.setAfwControlId(mSessionId);
3386
3387 GnssConfigGpsLock gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
3388 if (mAdapter.mSupportNfwControl) {
3389 ContextBase::mGps_conf.GPS_LOCK &= GNSS_CONFIG_GPS_LOCK_NI;
3390 gpsLock = ContextBase::mGps_conf.GPS_LOCK;
3391 }
3392 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
3393 mApi.setGpsLockSync(gpsLock);
3394 }));
3395 mAdapter.mXtraObserver.updateLockStatus(gpsLock);
3396 }
3397 mAdapter.reportResponse(err, mSessionId);
3398 }
3399 };
3400
3401 if (mContext != NULL) {
3402 sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
3403 } else {
3404 LOC_LOGE("%s]: Context is NULL", __func__);
3405 }
3406
3407 return sessionId;
3408 }
3409
3410 void
disableCommand(uint32_t id)3411 GnssAdapter::disableCommand(uint32_t id)
3412 {
3413 LOC_LOGD("%s]: id %u", __func__, id);
3414
3415 struct MsgDisableGnss : public LocMsg {
3416 GnssAdapter& mAdapter;
3417 LocApiBase& mApi;
3418 ContextBase& mContext;
3419 uint32_t mSessionId;
3420 inline MsgDisableGnss(GnssAdapter& adapter,
3421 LocApiBase& api,
3422 ContextBase& context,
3423 uint32_t sessionId) :
3424 LocMsg(),
3425 mAdapter(adapter),
3426 mApi(api),
3427 mContext(context),
3428 mSessionId(sessionId) {}
3429 inline virtual void proc() const {
3430 LocationError err = LOCATION_ERROR_SUCCESS;
3431 uint32_t afwControlId = mAdapter.getAfwControlId();
3432 if (afwControlId != mSessionId) {
3433 err = LOCATION_ERROR_ID_UNKNOWN;
3434 } else {
3435 mContext.modemPowerVote(false);
3436 mAdapter.setAfwControlId(0);
3437
3438 if (mAdapter.mSupportNfwControl) {
3439 /* We need to disable MO (AFW) */
3440 ContextBase::mGps_conf.GPS_LOCK |= GNSS_CONFIG_GPS_LOCK_MO;
3441 }
3442 GnssConfigGpsLock gpsLock = ContextBase::mGps_conf.GPS_LOCK;
3443 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
3444 mApi.setGpsLockSync(gpsLock);
3445 }));
3446 mAdapter.mXtraObserver.updateLockStatus(gpsLock);
3447 }
3448 mAdapter.reportResponse(err, mSessionId);
3449 }
3450 };
3451
3452 if (mContext != NULL) {
3453 sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
3454 }
3455
3456 }
3457
3458 void
reportPositionEvent(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask,GnssDataNotification * pDataNotify,int msInWeek)3459 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
3460 const GpsLocationExtended& locationExtended,
3461 enum loc_sess_status status,
3462 LocPosTechMask techMask,
3463 GnssDataNotification* pDataNotify,
3464 int msInWeek)
3465 {
3466 // this position is from QMI LOC API, then send report to engine hub
3467 // also, send out SPE fix promptly to the clients that have registered
3468 // with SPE report
3469 LOC_LOGd("reportPositionEvent, eng type: %d, unpro %d, sess status %d",
3470 locationExtended.locOutputEngType, ulpLocation.unpropagatedPosition,
3471 status);
3472
3473 if (true == initEngHubProxy()){
3474 // send the SPE fix to engine hub
3475 mEngHubProxy->gnssReportPosition(ulpLocation, locationExtended, status);
3476 // report out all SPE fix if it is not propagated, even for failed fix
3477 if (false == ulpLocation.unpropagatedPosition) {
3478 EngineLocationInfo engLocationInfo = {};
3479 engLocationInfo.location = ulpLocation;
3480 engLocationInfo.locationExtended = locationExtended;
3481 engLocationInfo.sessionStatus = status;
3482 reportEnginePositionsEvent(1, &engLocationInfo);
3483 }
3484 return;
3485 }
3486
3487 // unpropagated report: is only for engine hub to consume and no need
3488 // to send out to the clients
3489 if (true == ulpLocation.unpropagatedPosition) {
3490 return;
3491 }
3492
3493 // Fix is from QMI, and it is not an unpropagated position and engine hub
3494 // is not loaded, queue the message when message is processed, the position
3495 // can be dispatched to requesting client that registers for SPE report
3496 struct MsgReportPosition : public LocMsg {
3497 GnssAdapter& mAdapter;
3498 const UlpLocation mUlpLocation;
3499 const GpsLocationExtended mLocationExtended;
3500 loc_sess_status mStatus;
3501 LocPosTechMask mTechMask;
3502 GnssDataNotification mDataNotify;
3503 int mMsInWeek;
3504 bool mbIsDataValid;
3505 inline MsgReportPosition(GnssAdapter& adapter,
3506 const UlpLocation& ulpLocation,
3507 const GpsLocationExtended& locationExtended,
3508 loc_sess_status status,
3509 LocPosTechMask techMask,
3510 GnssDataNotification* pDataNotify,
3511 int msInWeek) :
3512 LocMsg(),
3513 mAdapter(adapter),
3514 mUlpLocation(ulpLocation),
3515 mLocationExtended(locationExtended),
3516 mStatus(status),
3517 mTechMask(techMask),
3518 mMsInWeek(msInWeek) {
3519 memset(&mDataNotify, 0, sizeof(mDataNotify));
3520 if (pDataNotify != nullptr) {
3521 mDataNotify = *pDataNotify;
3522 mbIsDataValid = true;
3523 } else {
3524 mbIsDataValid = false;
3525 }
3526 }
3527 inline virtual void proc() const {
3528 // extract bug report info - this returns true if consumed by systemstatus
3529 SystemStatus* s = mAdapter.getSystemStatus();
3530 if ((nullptr != s) &&
3531 ((LOC_SESS_SUCCESS == mStatus) || (LOC_SESS_INTERMEDIATE == mStatus))){
3532 s->eventPosition(mUlpLocation, mLocationExtended);
3533 }
3534 mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
3535 if (true == mbIsDataValid) {
3536 if (-1 != mMsInWeek) {
3537 mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
3538 mMsInWeek);
3539 }
3540 mAdapter.reportData((GnssDataNotification&)mDataNotify);
3541 }
3542 }
3543 };
3544
3545 sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended,
3546 status, techMask,
3547 pDataNotify, msInWeek));
3548 }
3549
3550 void
reportEnginePositionsEvent(unsigned int count,EngineLocationInfo * locationArr)3551 GnssAdapter::reportEnginePositionsEvent(unsigned int count,
3552 EngineLocationInfo* locationArr)
3553 {
3554 struct MsgReportEnginePositions : public LocMsg {
3555 GnssAdapter& mAdapter;
3556 unsigned int mCount;
3557 EngineLocationInfo mEngLocInfo[LOC_OUTPUT_ENGINE_COUNT];
3558 inline MsgReportEnginePositions(GnssAdapter& adapter,
3559 unsigned int count,
3560 EngineLocationInfo* locationArr) :
3561 LocMsg(),
3562 mAdapter(adapter),
3563 mCount(count) {
3564 if (mCount > LOC_OUTPUT_ENGINE_COUNT) {
3565 mCount = LOC_OUTPUT_ENGINE_COUNT;
3566 }
3567 if (mCount > 0) {
3568 memcpy(mEngLocInfo, locationArr, sizeof(EngineLocationInfo)*mCount);
3569 }
3570 }
3571 inline virtual void proc() const {
3572 mAdapter.reportEnginePositions(mCount, mEngLocInfo);
3573 }
3574 };
3575
3576 sendMsg(new MsgReportEnginePositions(*this, count, locationArr));
3577 }
3578
3579 bool
needReportForGnssClient(const UlpLocation & ulpLocation,enum loc_sess_status status,LocPosTechMask techMask)3580 GnssAdapter::needReportForGnssClient(const UlpLocation& ulpLocation,
3581 enum loc_sess_status status,
3582 LocPosTechMask techMask) {
3583 bool reported = false;
3584
3585 // if engine hub is enabled, aka, any of the engine services is enabled,
3586 // then always output position reported by engine hub to requesting client
3587 if (true == initEngHubProxy()) {
3588 reported = true;
3589 } else {
3590 reported = LocApiBase::needReport(ulpLocation, status, techMask);
3591 }
3592 return reported;
3593 }
3594
3595 bool
needReportForFlpClient(enum loc_sess_status status,LocPosTechMask techMask)3596 GnssAdapter::needReportForFlpClient(enum loc_sess_status status,
3597 LocPosTechMask techMask) {
3598 if ((status == LOC_SESS_INTERMEDIATE) &&
3599 !(techMask & LOC_POS_TECH_MASK_SENSORS) &&
3600 (!getAllowFlpNetworkFixes())) {
3601 return false;
3602 } else {
3603 return true;
3604 }
3605 }
3606
3607 bool
isFlpClient(LocationCallbacks & locationCallbacks)3608 GnssAdapter::isFlpClient(LocationCallbacks& locationCallbacks)
3609 {
3610 return (locationCallbacks.gnssLocationInfoCb == nullptr &&
3611 locationCallbacks.gnssSvCb == nullptr &&
3612 locationCallbacks.gnssNmeaCb == nullptr &&
3613 locationCallbacks.gnssDataCb == nullptr &&
3614 locationCallbacks.gnssMeasurementsCb == nullptr);
3615 }
3616
needToGenerateNmeaReport(const uint32_t & gpsTimeOfWeekMs,const struct timespec32_t & apTimeStamp)3617 bool GnssAdapter::needToGenerateNmeaReport(const uint32_t &gpsTimeOfWeekMs,
3618 const struct timespec32_t &apTimeStamp)
3619 {
3620 bool retVal = false;
3621 uint64_t currentTimeNsec = 0;
3622
3623 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTimeBasedTrackingSessions.empty()) {
3624 currentTimeNsec = (apTimeStamp.tv_sec * BILLION_NSEC + apTimeStamp.tv_nsec);
3625 if ((GNSS_NMEA_REPORT_RATE_NHZ == ContextBase::sNmeaReportRate) ||
3626 (GPS_DEFAULT_FIX_INTERVAL_MS <= mLocPositionMode.min_interval)) {
3627 retVal = true;
3628 } else { /*tbf is less than 1000 milli-seconds and NMEA reporting rate is set to 1Hz */
3629 /* Always send NMEA string for first position report
3630 * Send when gpsTimeOfWeekMs is closely aligned with integer boundary
3631 */
3632 if ((0 == mPrevNmeaRptTimeNsec) ||
3633 (0 != gpsTimeOfWeekMs) && (NMEA_MIN_THRESHOLD_MSEC >= (gpsTimeOfWeekMs % 1000))) {
3634 retVal = true;
3635 } else {
3636 uint64_t timeDiffMsec = ((currentTimeNsec - mPrevNmeaRptTimeNsec) / 1000000);
3637 // Send when the delta time becomes >= 1 sec
3638 if (NMEA_MAX_THRESHOLD_MSEC <= timeDiffMsec) {
3639 retVal = true;
3640 }
3641 }
3642 }
3643 if (true == retVal) {
3644 mPrevNmeaRptTimeNsec = currentTimeNsec;
3645 }
3646 }
3647 return retVal;
3648 }
3649
3650 // only fused report (when engine hub is enabled) or
3651 // SPE report (when engine hub is disabled) will reach this function
3652 void
reportPosition(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask)3653 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
3654 const GpsLocationExtended& locationExtended,
3655 enum loc_sess_status status,
3656 LocPosTechMask techMask)
3657 {
3658 bool reportToGnssClient = needReportForGnssClient(ulpLocation, status, techMask);
3659 bool reportToFlpClient = needReportForFlpClient(status, techMask);
3660
3661 if (reportToGnssClient || reportToFlpClient) {
3662 GnssLocationInfoNotification locationInfo = {};
3663 convertLocationInfo(locationInfo, locationExtended);
3664 convertLocation(locationInfo.location, ulpLocation, locationExtended, techMask);
3665
3666 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3667 if ((reportToFlpClient && isFlpClient(it->second)) ||
3668 (reportToGnssClient && !isFlpClient(it->second))) {
3669 if (nullptr != it->second.gnssLocationInfoCb) {
3670 it->second.gnssLocationInfoCb(locationInfo);
3671 } else if ((nullptr != it->second.engineLocationsInfoCb) &&
3672 (false == initEngHubProxy())) {
3673 // if engine hub is disabled, this is SPE fix from modem
3674 // we need to mark one copy marked as fused and one copy marked as PPE
3675 // and dispatch it to the engineLocationsInfoCb
3676 GnssLocationInfoNotification engLocationsInfo[2];
3677 engLocationsInfo[0] = locationInfo;
3678 engLocationsInfo[0].locOutputEngType = LOC_OUTPUT_ENGINE_FUSED;
3679 engLocationsInfo[0].flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
3680 engLocationsInfo[1] = locationInfo;
3681 it->second.engineLocationsInfoCb(2, engLocationsInfo);
3682 } else if (nullptr != it->second.trackingCb) {
3683 it->second.trackingCb(locationInfo.location);
3684 }
3685 }
3686 }
3687
3688 mGnssSvIdUsedInPosAvail = false;
3689 mGnssMbSvIdUsedInPosAvail = false;
3690 if (reportToGnssClient) {
3691 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
3692 mGnssSvIdUsedInPosAvail = true;
3693 mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
3694 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MULTIBAND) {
3695 mGnssMbSvIdUsedInPosAvail = true;
3696 mGnssMbSvIdUsedInPosition = locationExtended.gnss_mb_sv_used_ids;
3697 }
3698 }
3699
3700 // if PACE is enabled
3701 if ((true == mLocConfigInfo.paceConfigInfo.isValid) &&
3702 (true == mLocConfigInfo.paceConfigInfo.enable)) {
3703 // If fix has sensor contribution, and it is fused fix with DRE engine
3704 // contributing to the fix, inject to modem
3705 if ((LOC_POS_TECH_MASK_SENSORS & techMask) &&
3706 (locationInfo.flags & GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT) &&
3707 (locationInfo.locOutputEngType == LOC_OUTPUT_ENGINE_FUSED) &&
3708 (locationInfo.flags & GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT) &&
3709 (locationInfo.locOutputEngMask & DEAD_RECKONING_ENGINE)) {
3710 mLocApi->injectPosition(locationInfo, false);
3711 }
3712 }
3713 }
3714 }
3715
3716 if (needToGenerateNmeaReport(locationExtended.gpsTime.gpsTimeOfWeekMs,
3717 locationExtended.timeStamp.apTimeStamp)) {
3718 /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 &
3719 horReliability is not set. */
3720 bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) &&
3721 (0 == ulpLocation.gpsLocation.longitude) &&
3722 (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability));
3723 uint8_t generate_nmea = (reportToGnssClient && status != LOC_SESS_FAILURE && !blank_fix);
3724 bool custom_nmea_gga = (1 == ContextBase::mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED);
3725 std::vector<std::string> nmeaArraystr;
3726 loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo,
3727 generate_nmea, custom_nmea_gga, nmeaArraystr);
3728 stringstream ss;
3729 for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
3730 ss << *itor;
3731 }
3732 string s = ss.str();
3733 reportNmea(s.c_str(), s.length());
3734 }
3735 }
3736
3737 void
reportEnginePositions(unsigned int count,const EngineLocationInfo * locationArr)3738 GnssAdapter::reportEnginePositions(unsigned int count,
3739 const EngineLocationInfo* locationArr)
3740 {
3741 bool needReportEnginePositions = false;
3742 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3743 if (nullptr != it->second.engineLocationsInfoCb) {
3744 needReportEnginePositions = true;
3745 break;
3746 }
3747 }
3748
3749 GnssLocationInfoNotification locationInfo[LOC_OUTPUT_ENGINE_COUNT] = {};
3750 for (unsigned int i = 0; i < count; i++) {
3751 const EngineLocationInfo* engLocation = (locationArr+i);
3752 // if it is fused/default location, call reportPosition maintain legacy behavior
3753 if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
3754 (LOC_OUTPUT_ENGINE_FUSED == engLocation->locationExtended.locOutputEngType)) {
3755 reportPosition(engLocation->location,
3756 engLocation->locationExtended,
3757 engLocation->sessionStatus,
3758 engLocation->location.tech_mask);
3759 }
3760
3761 if (needReportEnginePositions) {
3762 convertLocationInfo(locationInfo[i], engLocation->locationExtended);
3763 convertLocation(locationInfo[i].location,
3764 engLocation->location,
3765 engLocation->locationExtended,
3766 engLocation->location.tech_mask);
3767 }
3768 }
3769
3770 if (needReportEnginePositions) {
3771 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3772 if (nullptr != it->second.engineLocationsInfoCb) {
3773 it->second.engineLocationsInfoCb(count, locationInfo);
3774 }
3775 }
3776 }
3777 }
3778
3779 void
reportSvEvent(const GnssSvNotification & svNotify,bool fromEngineHub)3780 GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
3781 bool fromEngineHub)
3782 {
3783 if (!fromEngineHub) {
3784 mEngHubProxy->gnssReportSv(svNotify);
3785 if (true == initEngHubProxy()){
3786 return;
3787 }
3788 }
3789
3790 struct MsgReportSv : public LocMsg {
3791 GnssAdapter& mAdapter;
3792 const GnssSvNotification mSvNotify;
3793 inline MsgReportSv(GnssAdapter& adapter,
3794 const GnssSvNotification& svNotify) :
3795 LocMsg(),
3796 mAdapter(adapter),
3797 mSvNotify(svNotify) {}
3798 inline virtual void proc() const {
3799 mAdapter.reportSv((GnssSvNotification&)mSvNotify);
3800 }
3801 };
3802
3803 sendMsg(new MsgReportSv(*this, svNotify));
3804 }
3805
3806 void
reportSv(GnssSvNotification & svNotify)3807 GnssAdapter::reportSv(GnssSvNotification& svNotify)
3808 {
3809 int numSv = svNotify.count;
3810 uint16_t gnssSvId = 0;
3811 uint64_t svUsedIdMask = 0;
3812 for (int i=0; i < numSv; i++) {
3813 svUsedIdMask = 0;
3814 gnssSvId = svNotify.gnssSvs[i].svId;
3815 GnssSignalTypeMask signalTypeMask = svNotify.gnssSvs[i].gnssSignalTypeMask;
3816 switch (svNotify.gnssSvs[i].type) {
3817 case GNSS_SV_TYPE_GPS:
3818 if (mGnssSvIdUsedInPosAvail) {
3819 if (mGnssMbSvIdUsedInPosAvail) {
3820 switch (signalTypeMask) {
3821 case GNSS_SIGNAL_GPS_L1CA:
3822 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1ca_sv_used_ids_mask;
3823 break;
3824 case GNSS_SIGNAL_GPS_L1C:
3825 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1c_sv_used_ids_mask;
3826 break;
3827 case GNSS_SIGNAL_GPS_L2:
3828 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l2_sv_used_ids_mask;
3829 break;
3830 case GNSS_SIGNAL_GPS_L5:
3831 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l5_sv_used_ids_mask;
3832 break;
3833 }
3834 } else {
3835 svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
3836 }
3837 }
3838 break;
3839 case GNSS_SV_TYPE_GLONASS:
3840 if (mGnssSvIdUsedInPosAvail) {
3841 if (mGnssMbSvIdUsedInPosAvail) {
3842 switch (signalTypeMask) {
3843 case GNSS_SIGNAL_GLONASS_G1:
3844 svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g1_sv_used_ids_mask;
3845 break;
3846 case GNSS_SIGNAL_GLONASS_G2:
3847 svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g2_sv_used_ids_mask;
3848 break;
3849 }
3850 } else {
3851 svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
3852 }
3853 }
3854 // map the svid to respective constellation range 1..xx
3855 // then repective constellation svUsedIdMask map correctly to svid
3856 gnssSvId = gnssSvId - GLO_SV_PRN_MIN + 1;
3857 break;
3858 case GNSS_SV_TYPE_BEIDOU:
3859 if (mGnssSvIdUsedInPosAvail) {
3860 if (mGnssMbSvIdUsedInPosAvail) {
3861 switch (signalTypeMask) {
3862 case GNSS_SIGNAL_BEIDOU_B1I:
3863 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1i_sv_used_ids_mask;
3864 break;
3865 case GNSS_SIGNAL_BEIDOU_B1C:
3866 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1c_sv_used_ids_mask;
3867 break;
3868 case GNSS_SIGNAL_BEIDOU_B2I:
3869 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2i_sv_used_ids_mask;
3870 break;
3871 case GNSS_SIGNAL_BEIDOU_B2AI:
3872 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2ai_sv_used_ids_mask;
3873 break;
3874 case GNSS_SIGNAL_BEIDOU_B2AQ:
3875 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2aq_sv_used_ids_mask;
3876 break;
3877 }
3878 } else {
3879 svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
3880 }
3881 }
3882 gnssSvId = gnssSvId - BDS_SV_PRN_MIN + 1;
3883 break;
3884 case GNSS_SV_TYPE_GALILEO:
3885 if (mGnssSvIdUsedInPosAvail) {
3886 if (mGnssMbSvIdUsedInPosAvail) {
3887 switch (signalTypeMask) {
3888 case GNSS_SIGNAL_GALILEO_E1:
3889 svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e1_sv_used_ids_mask;
3890 break;
3891 case GNSS_SIGNAL_GALILEO_E5A:
3892 svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5a_sv_used_ids_mask;
3893 break;
3894 case GNSS_SIGNAL_GALILEO_E5B:
3895 svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5b_sv_used_ids_mask;
3896 break;
3897 }
3898 } else {
3899 svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
3900 }
3901 }
3902 gnssSvId = gnssSvId - GAL_SV_PRN_MIN + 1;
3903 break;
3904 case GNSS_SV_TYPE_QZSS:
3905 if (mGnssSvIdUsedInPosAvail) {
3906 if (mGnssMbSvIdUsedInPosAvail) {
3907 switch (signalTypeMask) {
3908 case GNSS_SIGNAL_QZSS_L1CA:
3909 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1ca_sv_used_ids_mask;
3910 break;
3911 case GNSS_SIGNAL_QZSS_L1S:
3912 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1s_sv_used_ids_mask;
3913 break;
3914 case GNSS_SIGNAL_QZSS_L2:
3915 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l2_sv_used_ids_mask;
3916 break;
3917 case GNSS_SIGNAL_QZSS_L5:
3918 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l5_sv_used_ids_mask;
3919 break;
3920 }
3921 } else {
3922 svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
3923 }
3924 }
3925 gnssSvId = gnssSvId - QZSS_SV_PRN_MIN + 1;
3926 break;
3927 case GNSS_SV_TYPE_NAVIC:
3928 if (mGnssSvIdUsedInPosAvail) {
3929 svUsedIdMask = mGnssSvIdUsedInPosition.navic_sv_used_ids_mask;
3930 }
3931 gnssSvId = gnssSvId - NAVIC_SV_PRN_MIN + 1;
3932 break;
3933 default:
3934 svUsedIdMask = 0;
3935 break;
3936 }
3937
3938 // If SV ID was used in previous position fix, then set USED_IN_FIX
3939 // flag, else clear the USED_IN_FIX flag.
3940 if (svFitsMask(svUsedIdMask, gnssSvId) && (svUsedIdMask & (1ULL << (gnssSvId - 1)))) {
3941 svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
3942 }
3943 }
3944
3945 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3946 if (nullptr != it->second.gnssSvCb) {
3947 it->second.gnssSvCb(svNotify);
3948 }
3949 }
3950
3951 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
3952 !mTimeBasedTrackingSessions.empty()) {
3953 std::vector<std::string> nmeaArraystr;
3954 loc_nmea_generate_sv(svNotify, nmeaArraystr);
3955 stringstream ss;
3956 for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
3957 ss << *itor;
3958 }
3959 string s = ss.str();
3960 reportNmea(s.c_str(), s.length());
3961 }
3962
3963 mGnssSvIdUsedInPosAvail = false;
3964 }
3965
3966 void
reportNmeaEvent(const char * nmea,size_t length)3967 GnssAdapter::reportNmeaEvent(const char* nmea, size_t length)
3968 {
3969 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
3970 !loc_nmea_is_debug(nmea, length)) {
3971 return;
3972 }
3973
3974 struct MsgReportNmea : public LocMsg {
3975 GnssAdapter& mAdapter;
3976 const char* mNmea;
3977 size_t mLength;
3978 inline MsgReportNmea(GnssAdapter& adapter,
3979 const char* nmea,
3980 size_t length) :
3981 LocMsg(),
3982 mAdapter(adapter),
3983 mNmea(new char[length+1]),
3984 mLength(length) {
3985 if (mNmea == nullptr) {
3986 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
3987 return;
3988 }
3989 strlcpy((char*)mNmea, nmea, length+1);
3990 }
3991 inline virtual ~MsgReportNmea()
3992 {
3993 delete[] mNmea;
3994 }
3995 inline virtual void proc() const {
3996 // extract bug report info - this returns true if consumed by systemstatus
3997 bool ret = false;
3998 SystemStatus* s = mAdapter.getSystemStatus();
3999 if (nullptr != s) {
4000 ret = s->setNmeaString(mNmea, mLength);
4001 }
4002 if (false == ret) {
4003 // forward NMEA message to upper layer
4004 mAdapter.reportNmea(mNmea, mLength);
4005 }
4006 }
4007 };
4008
4009 sendMsg(new MsgReportNmea(*this, nmea, length));
4010 }
4011
4012 void
reportNmea(const char * nmea,size_t length)4013 GnssAdapter::reportNmea(const char* nmea, size_t length)
4014 {
4015 GnssNmeaNotification nmeaNotification = {};
4016 nmeaNotification.size = sizeof(GnssNmeaNotification);
4017
4018 struct timeval tv;
4019 gettimeofday(&tv, (struct timezone *) NULL);
4020 int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
4021 nmeaNotification.timestamp = now;
4022 nmeaNotification.nmea = nmea;
4023 nmeaNotification.length = length;
4024
4025 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4026 if (nullptr != it->second.gnssNmeaCb) {
4027 it->second.gnssNmeaCb(nmeaNotification);
4028 }
4029 }
4030 }
4031
4032 void
reportDataEvent(const GnssDataNotification & dataNotify,int msInWeek)4033 GnssAdapter::reportDataEvent(const GnssDataNotification& dataNotify,
4034 int msInWeek)
4035 {
4036 struct MsgReportData : public LocMsg {
4037 GnssAdapter& mAdapter;
4038 GnssDataNotification mDataNotify;
4039 int mMsInWeek;
4040 inline MsgReportData(GnssAdapter& adapter,
4041 const GnssDataNotification& dataNotify,
4042 int msInWeek) :
4043 LocMsg(),
4044 mAdapter(adapter),
4045 mDataNotify(dataNotify),
4046 mMsInWeek(msInWeek) {
4047 }
4048 inline virtual void proc() const {
4049 if (-1 != mMsInWeek) {
4050 mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
4051 mMsInWeek);
4052 }
4053 mAdapter.reportData((GnssDataNotification&)mDataNotify);
4054 }
4055 };
4056
4057 sendMsg(new MsgReportData(*this, dataNotify, msInWeek));
4058 }
4059
4060 void
reportData(GnssDataNotification & dataNotify)4061 GnssAdapter::reportData(GnssDataNotification& dataNotify)
4062 {
4063 for (int sig = 0; sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
4064 if (GNSS_LOC_DATA_JAMMER_IND_BIT ==
4065 (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_JAMMER_IND_BIT)) {
4066 LOC_LOGv("jammerInd[%d]=%f", sig, dataNotify.jammerInd[sig]);
4067 }
4068 if (GNSS_LOC_DATA_AGC_BIT ==
4069 (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_AGC_BIT)) {
4070 LOC_LOGv("agc[%d]=%f", sig, dataNotify.agc[sig]);
4071 }
4072 }
4073 for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
4074 if (nullptr != it->second.gnssDataCb) {
4075 it->second.gnssDataCb(dataNotify);
4076 }
4077 }
4078 }
4079
4080 bool
requestNiNotifyEvent(const GnssNiNotification & notify,const void * data,const LocInEmergency emergencyState)4081 GnssAdapter::requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* data,
4082 const LocInEmergency emergencyState)
4083 {
4084 LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
4085 "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
4086 __func__, notify.type, notify.timeout, notify.timeoutResponse,
4087 notify.requestor, notify.requestorEncoding,
4088 notify.message, notify.messageEncoding, notify.extras);
4089
4090 struct MsgReportNiNotify : public LocMsg {
4091 GnssAdapter& mAdapter;
4092 LocApiBase& mApi;
4093 const GnssNiNotification mNotify;
4094 const void* mData;
4095 const LocInEmergency mEmergencyState;
4096 inline MsgReportNiNotify(GnssAdapter& adapter,
4097 LocApiBase& api,
4098 const GnssNiNotification& notify,
4099 const void* data,
4100 const LocInEmergency emergencyState) :
4101 LocMsg(),
4102 mAdapter(adapter),
4103 mApi(api),
4104 mNotify(notify),
4105 mData(data),
4106 mEmergencyState(emergencyState) {}
4107 inline virtual void proc() const {
4108 bool bIsInEmergency = false;
4109 bool bInformNiAccept = false;
4110
4111 bIsInEmergency = ((LOC_IN_EMERGENCY_UNKNOWN == mEmergencyState) &&
4112 mAdapter.getE911State()) || // older modems
4113 (LOC_IN_EMERGENCY_SET == mEmergencyState); // newer modems
4114
4115 if ((mAdapter.mSupportNfwControl || 0 == mAdapter.getAfwControlId()) &&
4116 (GNSS_NI_TYPE_SUPL == mNotify.type || GNSS_NI_TYPE_EMERGENCY_SUPL == mNotify.type)
4117 && !bIsInEmergency &&
4118 !(GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT & mNotify.options) &&
4119 (GNSS_CONFIG_GPS_LOCK_NI & ContextBase::mGps_conf.GPS_LOCK) &&
4120 1 == ContextBase::mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED) {
4121 /* If all these conditions are TRUE, then deny the NI Request:
4122 -'Q' Lock behavior OR 'P' Lock behavior and GNSS is Locked
4123 -NI SUPL Request type or NI SUPL Emergency Request type
4124 -NOT in an Emergency Call Session
4125 -NOT Privacy Override option
4126 -NFW is locked and config item NI_SUPL_DENY_ON_NFW_LOCKED = 1 */
4127 mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData);
4128 } else if (GNSS_NI_TYPE_EMERGENCY_SUPL == mNotify.type) {
4129 bInformNiAccept = bIsInEmergency ||
4130 (GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO == ContextBase::mGps_conf.SUPL_ES);
4131
4132 if (bInformNiAccept) {
4133 mAdapter.requestNiNotify(mNotify, mData, bInformNiAccept);
4134 } else {
4135 mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData);
4136 }
4137 } else if (GNSS_NI_TYPE_CONTROL_PLANE == mNotify.type) {
4138 if (bIsInEmergency && (1 == ContextBase::mGps_conf.CP_MTLR_ES)) {
4139 mApi.informNiResponse(GNSS_NI_RESPONSE_ACCEPT, mData);
4140 }
4141 else {
4142 mAdapter.requestNiNotify(mNotify, mData, false);
4143 }
4144 } else {
4145 mAdapter.requestNiNotify(mNotify, mData, false);
4146 }
4147 }
4148 };
4149
4150 sendMsg(new MsgReportNiNotify(*this, *mLocApi, notify, data, emergencyState));
4151
4152 return true;
4153 }
4154
4155 void
reportLocationSystemInfoEvent(const LocationSystemInfo & locationSystemInfo)4156 GnssAdapter::reportLocationSystemInfoEvent(const LocationSystemInfo & locationSystemInfo) {
4157
4158 // send system info to engine hub
4159 mEngHubProxy->gnssReportSystemInfo(locationSystemInfo);
4160
4161 struct MsgLocationSystemInfo : public LocMsg {
4162 GnssAdapter& mAdapter;
4163 LocationSystemInfo mSystemInfo;
4164 inline MsgLocationSystemInfo(GnssAdapter& adapter,
4165 const LocationSystemInfo& systemInfo) :
4166 LocMsg(),
4167 mAdapter(adapter),
4168 mSystemInfo(systemInfo) {}
4169 inline virtual void proc() const {
4170 mAdapter.reportLocationSystemInfo(mSystemInfo);
4171 }
4172 };
4173
4174 sendMsg(new MsgLocationSystemInfo(*this, locationSystemInfo));
4175 }
4176
4177 void
reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo)4178 GnssAdapter::reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo) {
4179 // save the info into the master copy piece by piece, as other system info
4180 // may come at different time
4181 if (locationSystemInfo.systemInfoMask & LOCATION_SYS_INFO_LEAP_SECOND) {
4182 mLocSystemInfo.systemInfoMask |= LOCATION_SYS_INFO_LEAP_SECOND;
4183
4184 const LeapSecondSystemInfo &srcLeapSecondSysInfo = locationSystemInfo.leapSecondSysInfo;
4185 LeapSecondSystemInfo &dstLeapSecondSysInfo = mLocSystemInfo.leapSecondSysInfo;
4186 if (srcLeapSecondSysInfo.leapSecondInfoMask &
4187 LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT) {
4188 dstLeapSecondSysInfo.leapSecondInfoMask |=
4189 LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT;
4190 dstLeapSecondSysInfo.leapSecondCurrent = srcLeapSecondSysInfo.leapSecondCurrent;
4191 }
4192 // once leap second change event is complete, modem may send up event invalidate the leap
4193 // second change info while AP is still processing report during leap second transition
4194 // so, we choose to keep this info around even though it is old
4195 if (srcLeapSecondSysInfo.leapSecondInfoMask & LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT) {
4196 dstLeapSecondSysInfo.leapSecondInfoMask |= LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT;
4197 dstLeapSecondSysInfo.leapSecondChangeInfo = srcLeapSecondSysInfo.leapSecondChangeInfo;
4198 }
4199 }
4200
4201 // we received new info, inform client of the newly received info
4202 if (locationSystemInfo.systemInfoMask) {
4203 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4204 if (it->second.locationSystemInfoCb != nullptr) {
4205 it->second.locationSystemInfoCb(locationSystemInfo);
4206 }
4207 }
4208 }
4209 }
4210
niThreadProc(void * args)4211 static void* niThreadProc(void *args)
4212 {
4213 NiSession* pSession = (NiSession*)args;
4214 int rc = 0; /* return code from pthread calls */
4215
4216 struct timespec present_time;
4217 struct timespec expire_time;
4218
4219 pthread_mutex_lock(&pSession->tLock);
4220 /* Calculate absolute expire time */
4221 clock_gettime(CLOCK_MONOTONIC, &present_time);
4222 expire_time.tv_sec = present_time.tv_sec + pSession->respTimeLeft;
4223 expire_time.tv_nsec = present_time.tv_nsec;
4224 LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
4225 __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
4226
4227 while (!pSession->respRecvd) {
4228 rc = pthread_cond_timedwait(&pSession->tCond,
4229 &pSession->tLock,
4230 &expire_time);
4231 if (rc == ETIMEDOUT) {
4232 pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
4233 LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
4234 __func__, rc);
4235 break;
4236 }
4237 }
4238 LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
4239 "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
4240 pSession->respRecvd = false; /* Reset the user response flag for the next session*/
4241
4242 // adding this check to support modem restart, in which case, we need the thread
4243 // to exit without calling sending data. We made sure that rawRequest is NULL in
4244 // loc_eng_ni_reset_on_engine_restart()
4245 GnssAdapter* adapter = pSession->adapter;
4246 GnssNiResponse resp;
4247 void* rawRequest = NULL;
4248 bool sendResponse = false;
4249
4250 if (NULL != pSession->rawRequest) {
4251 if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
4252 resp = pSession->resp;
4253 rawRequest = pSession->rawRequest;
4254 sendResponse = true;
4255 } else {
4256 free(pSession->rawRequest);
4257 }
4258 pSession->rawRequest = NULL;
4259 }
4260 pthread_mutex_unlock(&pSession->tLock);
4261
4262 pSession->respTimeLeft = 0;
4263 pSession->reqID = 0;
4264
4265 if (sendResponse) {
4266 adapter->gnssNiResponseCommand(resp, rawRequest);
4267 }
4268
4269 return NULL;
4270 }
4271
4272 bool
requestNiNotify(const GnssNiNotification & notify,const void * data,const bool bInformNiAccept)4273 GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data,
4274 const bool bInformNiAccept)
4275 {
4276 NiSession* pSession = NULL;
4277 gnssNiCallback gnssNiCb = nullptr;
4278
4279 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4280 if (nullptr != it->second.gnssNiCb) {
4281 gnssNiCb = it->second.gnssNiCb;
4282 break;
4283 }
4284 }
4285 if (nullptr == gnssNiCb) {
4286 if (GNSS_NI_TYPE_EMERGENCY_SUPL == notify.type) {
4287 if (bInformNiAccept) {
4288 mLocApi->informNiResponse(GNSS_NI_RESPONSE_ACCEPT, data);
4289 NiData& niData = getNiData();
4290 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
4291 if (NULL != niData.session.rawRequest) {
4292 pthread_mutex_lock(&niData.session.tLock);
4293 niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
4294 niData.session.respRecvd = true;
4295 pthread_cond_signal(&niData.session.tCond);
4296 pthread_mutex_unlock(&niData.session.tLock);
4297 }
4298 }
4299 }
4300 EXIT_LOG(%s, "no clients with gnssNiCb.");
4301 return false;
4302 }
4303
4304 if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
4305 if (NULL != mNiData.sessionEs.rawRequest) {
4306 LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
4307 __func__, notify.type);
4308 if (NULL != data) {
4309 free((void*)data);
4310 }
4311 } else {
4312 pSession = &mNiData.sessionEs;
4313 }
4314 } else {
4315 if (NULL != mNiData.session.rawRequest ||
4316 NULL != mNiData.sessionEs.rawRequest) {
4317 LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
4318 __func__, notify.type);
4319 if (NULL != data) {
4320 free((void*)data);
4321 }
4322 } else {
4323 pSession = &mNiData.session;
4324 }
4325 }
4326
4327 if (pSession) {
4328 /* Save request */
4329 pSession->rawRequest = (void*)data;
4330 pSession->reqID = ++mNiData.reqIDCounter;
4331 pSession->adapter = this;
4332
4333 int sessionId = pSession->reqID;
4334
4335 /* For robustness, spawn a thread at this point to timeout to clear up the notification
4336 * status, even though the OEM layer in java does not do so.
4337 **/
4338 pSession->respTimeLeft =
4339 5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
4340
4341 int rc = 0;
4342 rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
4343 if (rc) {
4344 LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
4345 }
4346 rc = pthread_detach(pSession->thread);
4347 if (rc) {
4348 LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
4349 }
4350
4351 if (nullptr != gnssNiCb) {
4352 gnssNiCb(sessionId, notify);
4353 }
4354 }
4355
4356 return true;
4357 }
4358
4359 void
reportGnssMeasurementsEvent(const GnssMeasurements & gnssMeasurements,int msInWeek)4360 GnssAdapter::reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements,
4361 int msInWeek)
4362 {
4363 LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek);
4364
4365 if (0 != gnssMeasurements.gnssMeasNotification.count) {
4366 struct MsgReportGnssMeasurementData : public LocMsg {
4367 GnssAdapter& mAdapter;
4368 GnssMeasurements mGnssMeasurements;
4369 GnssMeasurementsNotification mMeasurementsNotify;
4370 inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
4371 const GnssMeasurements& gnssMeasurements,
4372 int msInWeek) :
4373 LocMsg(),
4374 mAdapter(adapter),
4375 mMeasurementsNotify(gnssMeasurements.gnssMeasNotification) {
4376 if (-1 != msInWeek) {
4377 mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek);
4378 }
4379 }
4380 inline virtual void proc() const {
4381 mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
4382 }
4383 };
4384
4385 sendMsg(new MsgReportGnssMeasurementData(*this, gnssMeasurements, msInWeek));
4386 }
4387 mEngHubProxy->gnssReportSvMeasurement(gnssMeasurements.gnssSvMeasurementSet);
4388 if (mDGnssNeedReport) {
4389 reportDGnssDataUsable(gnssMeasurements.gnssSvMeasurementSet);
4390 }
4391 }
4392
4393 void
reportGnssMeasurementData(const GnssMeasurementsNotification & measurements)4394 GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurements)
4395 {
4396 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4397 if (nullptr != it->second.gnssMeasurementsCb) {
4398 it->second.gnssMeasurementsCb(measurements);
4399 }
4400 }
4401 }
4402
4403 void
reportDGnssDataUsable(const GnssSvMeasurementSet & svMeasurementSet)4404 GnssAdapter::reportDGnssDataUsable(const GnssSvMeasurementSet &svMeasurementSet)
4405 {
4406 uint32_t i;
4407 bool preDGnssDataUsage = mDGnssDataUsage;
4408
4409 mDGnssDataUsage = false;
4410 for (i = 0; i < svMeasurementSet.svMeasCount; i++) {
4411 const Gnss_SVMeasurementStructType& svMeas = svMeasurementSet.svMeas[i];
4412 if (svMeas.dgnssSvMeas.dgnssMeasStatus) {
4413 mDGnssDataUsage = true;
4414 break;
4415 }
4416 }
4417 if (mDGnssDataUsage != preDGnssDataUsage) {
4418 if (mCdfwInterface) {
4419 mCdfwInterface->reportUsable(mQDgnssListenerHDL, mDGnssDataUsage);
4420 }
4421 }
4422 }
4423
4424 void
reportSvPolynomialEvent(GnssSvPolynomial & svPolynomial)4425 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
4426 {
4427 LOC_LOGD("%s]: ", __func__);
4428 mEngHubProxy->gnssReportSvPolynomial(svPolynomial);
4429 }
4430
4431 void
reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris)4432 GnssAdapter::reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris)
4433 {
4434 LOC_LOGD("%s]:", __func__);
4435 mEngHubProxy->gnssReportSvEphemeris(svEphemeris);
4436 }
4437
4438
4439 bool
requestOdcpiEvent(OdcpiRequestInfo & request)4440 GnssAdapter::requestOdcpiEvent(OdcpiRequestInfo& request)
4441 {
4442 struct MsgRequestOdcpi : public LocMsg {
4443 GnssAdapter& mAdapter;
4444 OdcpiRequestInfo mOdcpiRequest;
4445 inline MsgRequestOdcpi(GnssAdapter& adapter, OdcpiRequestInfo& request) :
4446 LocMsg(),
4447 mAdapter(adapter),
4448 mOdcpiRequest(request) {}
4449 inline virtual void proc() const {
4450 mAdapter.requestOdcpi(mOdcpiRequest);
4451 }
4452 };
4453
4454 sendMsg(new MsgRequestOdcpi(*this, request));
4455 return true;
4456 }
4457
requestOdcpi(const OdcpiRequestInfo & request)4458 void GnssAdapter::requestOdcpi(const OdcpiRequestInfo& request)
4459 {
4460 if (nullptr != mOdcpiRequestCb) {
4461 LOC_LOGd("request: type %d, tbf %d, isEmergency %d"
4462 " requestActive: %d timerActive: %d",
4463 request.type, request.tbfMillis, request.isEmergencyMode,
4464 mOdcpiRequestActive, mOdcpiTimer.isActive());
4465 // ODCPI START and ODCPI STOP from modem can come in quick succession
4466 // so the mOdcpiTimer helps avoid spamming the framework as well as
4467 // extending the odcpi session past 30 seconds if needed
4468 if (ODCPI_REQUEST_TYPE_START == request.type) {
4469 if (false == mOdcpiRequestActive && false == mOdcpiTimer.isActive()) {
4470 mOdcpiRequestCb(request);
4471 mOdcpiRequestActive = true;
4472 mOdcpiTimer.start();
4473 // if the current active odcpi session is non-emergency, and the new
4474 // odcpi request is emergency, replace the odcpi request with new request
4475 // and restart the timer
4476 } else if (false == mOdcpiRequest.isEmergencyMode &&
4477 true == request.isEmergencyMode) {
4478 mOdcpiRequestCb(request);
4479 mOdcpiRequestActive = true;
4480 if (true == mOdcpiTimer.isActive()) {
4481 mOdcpiTimer.restart();
4482 } else {
4483 mOdcpiTimer.start();
4484 }
4485 // if ODCPI request is not active but the timer is active, then
4486 // just update the active state and wait for timer to expire
4487 // before requesting new ODCPI to avoid spamming ODCPI requests
4488 } else if (false == mOdcpiRequestActive && true == mOdcpiTimer.isActive()) {
4489 mOdcpiRequestActive = true;
4490 }
4491 mOdcpiRequest = request;
4492 // the request is being stopped, but allow timer to expire first
4493 // before stopping the timer just in case more ODCPI requests come
4494 // to avoid spamming more odcpi requests to the framework
4495 } else {
4496 mOdcpiRequestActive = false;
4497 }
4498 } else {
4499 LOC_LOGw("ODCPI request not supported");
4500 }
4501 }
4502
reportDeleteAidingDataEvent(GnssAidingData & aidingData)4503 bool GnssAdapter::reportDeleteAidingDataEvent(GnssAidingData& aidingData)
4504 {
4505 LOC_LOGD("%s]:", __func__);
4506 mEngHubProxy->gnssDeleteAidingData(aidingData);
4507 return true;
4508 }
4509
reportKlobucharIonoModelEvent(GnssKlobucharIonoModel & ionoModel)4510 bool GnssAdapter::reportKlobucharIonoModelEvent(GnssKlobucharIonoModel & ionoModel)
4511 {
4512 LOC_LOGD("%s]:", __func__);
4513 mEngHubProxy->gnssReportKlobucharIonoModel(ionoModel);
4514 return true;
4515 }
4516
reportGnssAdditionalSystemInfoEvent(GnssAdditionalSystemInfo & additionalSystemInfo)4517 bool GnssAdapter::reportGnssAdditionalSystemInfoEvent(
4518 GnssAdditionalSystemInfo & additionalSystemInfo)
4519 {
4520 LOC_LOGD("%s]:", __func__);
4521 mEngHubProxy->gnssReportAdditionalSystemInfo(additionalSystemInfo);
4522 return true;
4523 }
4524
initOdcpiCommand(const OdcpiRequestCallback & callback)4525 void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback)
4526 {
4527 struct MsgInitOdcpi : public LocMsg {
4528 GnssAdapter& mAdapter;
4529 OdcpiRequestCallback mOdcpiCb;
4530 inline MsgInitOdcpi(GnssAdapter& adapter,
4531 const OdcpiRequestCallback& callback) :
4532 LocMsg(),
4533 mAdapter(adapter),
4534 mOdcpiCb(callback) {}
4535 inline virtual void proc() const {
4536 mAdapter.initOdcpi(mOdcpiCb);
4537 }
4538 };
4539
4540 sendMsg(new MsgInitOdcpi(*this, callback));
4541 }
4542
initOdcpi(const OdcpiRequestCallback & callback)4543 void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback)
4544 {
4545 mOdcpiRequestCb = callback;
4546
4547 /* Register for WIFI request */
4548 updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI,
4549 LOC_REGISTRATION_MASK_ENABLED);
4550 }
4551
injectOdcpiCommand(const Location & location)4552 void GnssAdapter::injectOdcpiCommand(const Location& location)
4553 {
4554 struct MsgInjectOdcpi : public LocMsg {
4555 GnssAdapter& mAdapter;
4556 Location mLocation;
4557 inline MsgInjectOdcpi(GnssAdapter& adapter, const Location& location) :
4558 LocMsg(),
4559 mAdapter(adapter),
4560 mLocation(location) {}
4561 inline virtual void proc() const {
4562 mAdapter.injectOdcpi(mLocation);
4563 }
4564 };
4565
4566 sendMsg(new MsgInjectOdcpi(*this, location));
4567 }
4568
injectOdcpi(const Location & location)4569 void GnssAdapter::injectOdcpi(const Location& location)
4570 {
4571 LOC_LOGd("ODCPI Injection: requestActive: %d timerActive: %d"
4572 "lat %.7f long %.7f",
4573 mOdcpiRequestActive, mOdcpiTimer.isActive(),
4574 location.latitude, location.longitude);
4575
4576 mLocApi->injectPosition(location, true);
4577 }
4578
4579 // Called in the context of LocTimer thread
timeOutCallback()4580 void OdcpiTimer::timeOutCallback()
4581 {
4582 if (nullptr != mAdapter) {
4583 mAdapter->odcpiTimerExpireEvent();
4584 }
4585 }
4586
4587 // Called in the context of LocTimer thread
odcpiTimerExpireEvent()4588 void GnssAdapter::odcpiTimerExpireEvent()
4589 {
4590 struct MsgOdcpiTimerExpire : public LocMsg {
4591 GnssAdapter& mAdapter;
4592 inline MsgOdcpiTimerExpire(GnssAdapter& adapter) :
4593 LocMsg(),
4594 mAdapter(adapter) {}
4595 inline virtual void proc() const {
4596 mAdapter.odcpiTimerExpire();
4597 }
4598 };
4599 sendMsg(new MsgOdcpiTimerExpire(*this));
4600 }
odcpiTimerExpire()4601 void GnssAdapter::odcpiTimerExpire()
4602 {
4603 LOC_LOGd("requestActive: %d timerActive: %d",
4604 mOdcpiRequestActive, mOdcpiTimer.isActive());
4605
4606 // if ODCPI request is still active after timer
4607 // expires, request again and restart timer
4608 if (mOdcpiRequestActive) {
4609 mOdcpiRequestCb(mOdcpiRequest);
4610 mOdcpiTimer.restart();
4611 } else {
4612 mOdcpiTimer.stop();
4613 }
4614 }
4615
4616 void
invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot)4617 GnssAdapter::invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot) {
4618 if (mGnssEnergyConsumedCb) {
4619 mGnssEnergyConsumedCb(energyConsumedSinceFirstBoot);
4620 mGnssEnergyConsumedCb = nullptr;
4621 }
4622 }
4623
4624 bool
reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot)4625 GnssAdapter::reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot){
4626 LOC_LOGD("%s]: %" PRIu64 " ", __func__, energyConsumedSinceFirstBoot);
4627
4628 struct MsgReportGnssGnssEngEnergyConsumed : public LocMsg {
4629 GnssAdapter& mAdapter;
4630 uint64_t mGnssEnergyConsumedSinceFirstBoot;
4631 inline MsgReportGnssGnssEngEnergyConsumed(GnssAdapter& adapter,
4632 uint64_t energyConsumed) :
4633 LocMsg(),
4634 mAdapter(adapter),
4635 mGnssEnergyConsumedSinceFirstBoot(energyConsumed) {}
4636 inline virtual void proc() const {
4637 mAdapter.invokeGnssEnergyConsumedCallback(mGnssEnergyConsumedSinceFirstBoot);
4638 }
4639 };
4640
4641 sendMsg(new MsgReportGnssGnssEngEnergyConsumed(*this, energyConsumedSinceFirstBoot));
4642 return true;
4643 }
4644
initDefaultAgps()4645 void GnssAdapter::initDefaultAgps() {
4646 LOC_LOGD("%s]: ", __func__);
4647
4648 void *handle = nullptr;
4649 if ((handle = dlopen("libloc_net_iface.so", RTLD_NOW)) == nullptr) {
4650 LOC_LOGD("%s]: libloc_net_iface.so not found !", __func__);
4651 return;
4652 }
4653
4654 LocAgpsGetAgpsCbInfo getAgpsCbInfo = (LocAgpsGetAgpsCbInfo)
4655 dlsym(handle, "LocNetIfaceAgps_getAgpsCbInfo");
4656 if (getAgpsCbInfo == nullptr) {
4657 LOC_LOGE("%s]: Failed to get method LocNetIfaceAgps_getStatusCb", __func__);
4658 dlclose(handle);
4659 return;
4660 }
4661
4662 AgpsCbInfo& cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this);
4663
4664 if (cbInfo.statusV4Cb == nullptr) {
4665 LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__);
4666 dlclose(handle);
4667 return;
4668 }
4669
4670 initAgps(cbInfo);
4671 }
4672
initDefaultAgpsCommand()4673 void GnssAdapter::initDefaultAgpsCommand() {
4674 LOC_LOGD("%s]: ", __func__);
4675
4676 struct MsgInitDefaultAgps : public LocMsg {
4677 GnssAdapter& mAdapter;
4678 inline MsgInitDefaultAgps(GnssAdapter& adapter) :
4679 LocMsg(),
4680 mAdapter(adapter) {
4681 }
4682 inline virtual void proc() const {
4683 mAdapter.initDefaultAgps();
4684 }
4685 };
4686
4687 sendMsg(new MsgInitDefaultAgps(*this));
4688 }
4689
4690 /* INIT LOC AGPS MANAGER */
4691
initAgps(const AgpsCbInfo & cbInfo)4692 void GnssAdapter::initAgps(const AgpsCbInfo& cbInfo) {
4693 LOC_LOGD("%s]:cbInfo.atlType - %d", __func__, cbInfo.atlType);
4694
4695 if (!((ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB) ||
4696 (ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA))) {
4697 return;
4698 }
4699
4700 mAgpsManager.createAgpsStateMachines(cbInfo);
4701 /* Register for AGPS event mask */
4702 updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
4703 LOC_REGISTRATION_MASK_ENABLED);
4704 }
4705
initAgpsCommand(const AgpsCbInfo & cbInfo)4706 void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){
4707 LOC_LOGI("GnssAdapter::initAgpsCommand");
4708
4709 /* Message to initialize AGPS module */
4710 struct AgpsMsgInit: public LocMsg {
4711 const AgpsCbInfo mCbInfo;
4712 GnssAdapter& mAdapter;
4713
4714 inline AgpsMsgInit(const AgpsCbInfo& cbInfo,
4715 GnssAdapter& adapter) :
4716 LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
4717 LOC_LOGV("AgpsMsgInit");
4718 }
4719
4720 inline virtual void proc() const {
4721 LOC_LOGV("AgpsMsgInit::proc()");
4722 mAdapter.initAgps(mCbInfo);
4723 }
4724 };
4725
4726 /* Send message to initialize AGPS Manager */
4727 sendMsg(new AgpsMsgInit(cbInfo, *this));
4728 }
4729
initNfwCommand(const NfwCbInfo & cbInfo)4730 void GnssAdapter::initNfwCommand(const NfwCbInfo& cbInfo) {
4731 LOC_LOGi("GnssAdapter::initNfwCommand");
4732
4733 /* Message to initialize NFW */
4734 struct MsgInitNfw : public LocMsg {
4735 const NfwCbInfo mCbInfo;
4736 GnssAdapter& mAdapter;
4737
4738 inline MsgInitNfw(const NfwCbInfo& cbInfo,
4739 GnssAdapter& adapter) :
4740 LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
4741 LOC_LOGv("MsgInitNfw");
4742 }
4743
4744 inline virtual void proc() const {
4745 LOC_LOGv("MsgInitNfw::proc()");
4746 mAdapter.initNfw(mCbInfo);
4747 }
4748 };
4749
4750 /* Send message to initialize NFW */
4751 sendMsg(new MsgInitNfw(cbInfo, *this));
4752 }
4753
reportNfwNotificationEvent(GnssNfwNotification & notification)4754 void GnssAdapter::reportNfwNotificationEvent(GnssNfwNotification& notification) {
4755 LOC_LOGi("GnssAdapter::reportNfwNotificationEvent");
4756
4757 struct MsgReportNfwNotification : public LocMsg {
4758 const GnssNfwNotification mNotification;
4759 GnssAdapter& mAdapter;
4760
4761 inline MsgReportNfwNotification(const GnssNfwNotification& notification,
4762 GnssAdapter& adapter) :
4763 LocMsg(), mNotification(notification), mAdapter(adapter) {
4764 LOC_LOGv("MsgReportNfwNotification");
4765 }
4766
4767 inline virtual void proc() const {
4768 LOC_LOGv("MsgReportNfwNotification::proc()");
4769 mAdapter.reportNfwNotification(mNotification);
4770 }
4771 };
4772
4773 sendMsg(new MsgReportNfwNotification(notification, *this));
4774 }
4775
4776 /* GnssAdapter::requestATL
4777 * Method triggered in QMI thread as part of handling below message:
4778 * eQMI_LOC_SERVER_REQUEST_OPEN_V02
4779 * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
4780 * eQMI_LOC_WWAN_TYPE_INTERNET_V02
4781 * eQMI_LOC_WWAN_TYPE_AGNSS_V02
4782 * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
requestATL(int connHandle,LocAGpsType agpsType,LocApnTypeMask apnTypeMask)4783 bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType,
4784 LocApnTypeMask apnTypeMask){
4785
4786 LOC_LOGI("GnssAdapter::requestATL handle=%d agpsType=0x%X apnTypeMask=0x%X",
4787 connHandle, agpsType, apnTypeMask);
4788
4789 sendMsg( new AgpsMsgRequestATL(
4790 &mAgpsManager, connHandle, (AGpsExtType)agpsType,
4791 apnTypeMask));
4792
4793 return true;
4794 }
4795
4796 /* GnssAdapter::releaseATL
4797 * Method triggered in QMI thread as part of handling below message:
4798 * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
4799 * Triggers teardown of an existing AGPS call */
releaseATL(int connHandle)4800 bool GnssAdapter::releaseATL(int connHandle){
4801
4802 LOC_LOGI("GnssAdapter::releaseATL");
4803
4804 /* Release SUPL/INTERNET/SUPL_ES ATL */
4805 struct AgpsMsgReleaseATL: public LocMsg {
4806
4807 AgpsManager* mAgpsManager;
4808 int mConnHandle;
4809
4810 inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
4811 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
4812
4813 LOC_LOGV("AgpsMsgReleaseATL");
4814 }
4815
4816 inline virtual void proc() const {
4817
4818 LOC_LOGV("AgpsMsgReleaseATL::proc()");
4819 mAgpsManager->releaseATL(mConnHandle);
4820 }
4821 };
4822
4823 sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
4824
4825 return true;
4826 }
4827
dataConnOpenCommand(AGpsExtType agpsType,const char * apnName,int apnLen,AGpsBearerType bearerType)4828 void GnssAdapter::dataConnOpenCommand(
4829 AGpsExtType agpsType,
4830 const char* apnName, int apnLen, AGpsBearerType bearerType){
4831
4832 LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
4833
4834 struct AgpsMsgAtlOpenSuccess: public LocMsg {
4835
4836 AgpsManager* mAgpsManager;
4837 AGpsExtType mAgpsType;
4838 char* mApnName;
4839 int mApnLen;
4840 AGpsBearerType mBearerType;
4841
4842 inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
4843 const char* apnName, int apnLen, AGpsBearerType bearerType) :
4844 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
4845 new char[apnLen + 1]), mApnLen(apnLen), mBearerType(bearerType) {
4846
4847 LOC_LOGV("AgpsMsgAtlOpenSuccess");
4848 if (mApnName == nullptr) {
4849 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
4850 // Reporting the failure here
4851 mAgpsManager->reportAtlClosed(mAgpsType);
4852 return;
4853 }
4854 memcpy(mApnName, apnName, apnLen);
4855 mApnName[apnLen] = 0;
4856 }
4857
4858 inline ~AgpsMsgAtlOpenSuccess() {
4859 delete[] mApnName;
4860 }
4861
4862 inline virtual void proc() const {
4863
4864 LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
4865 mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType);
4866 }
4867 };
4868 // Added inital length checks for apnlen check to avoid security issues
4869 // In case of failure reporting the same
4870 if (NULL == apnName || apnLen <= 0 || apnLen > MAX_APN_LEN ||
4871 (strlen(apnName) != (unsigned)apnLen)) {
4872 LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__);
4873 mAgpsManager.reportAtlClosed(agpsType);
4874 } else {
4875 sendMsg( new AgpsMsgAtlOpenSuccess(
4876 &mAgpsManager, agpsType, apnName, apnLen, bearerType));
4877 }
4878 }
4879
dataConnClosedCommand(AGpsExtType agpsType)4880 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
4881
4882 LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
4883
4884 struct AgpsMsgAtlClosed: public LocMsg {
4885
4886 AgpsManager* mAgpsManager;
4887 AGpsExtType mAgpsType;
4888
4889 inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
4890 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
4891
4892 LOC_LOGV("AgpsMsgAtlClosed");
4893 }
4894
4895 inline virtual void proc() const {
4896
4897 LOC_LOGV("AgpsMsgAtlClosed::proc()");
4898 mAgpsManager->reportAtlClosed(mAgpsType);
4899 }
4900 };
4901
4902 sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
4903 }
4904
dataConnFailedCommand(AGpsExtType agpsType)4905 void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
4906
4907 LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
4908
4909 struct AgpsMsgAtlOpenFailed: public LocMsg {
4910
4911 AgpsManager* mAgpsManager;
4912 AGpsExtType mAgpsType;
4913
4914 inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
4915 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
4916
4917 LOC_LOGV("AgpsMsgAtlOpenFailed");
4918 }
4919
4920 inline virtual void proc() const {
4921
4922 LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
4923 mAgpsManager->reportAtlOpenFailed(mAgpsType);
4924 }
4925 };
4926
4927 sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
4928 }
4929
convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo> & out,const GnssSvType & in_constellation,const SystemStatusReports & in)4930 void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
4931 const GnssSvType& in_constellation,
4932 const SystemStatusReports& in)
4933 {
4934 uint64_t sv_mask = 0ULL;
4935 uint32_t svid_min = 0;
4936 uint32_t svid_num = 0;
4937 uint32_t svid_idx = 0;
4938
4939 uint64_t eph_health_good_mask = 0ULL;
4940 uint64_t eph_health_bad_mask = 0ULL;
4941 uint64_t server_perdiction_available_mask = 0ULL;
4942 float server_perdiction_age = 0.0f;
4943
4944 // set constellationi based parameters
4945 switch (in_constellation) {
4946 case GNSS_SV_TYPE_GPS:
4947 svid_min = GNSS_BUGREPORT_GPS_MIN;
4948 svid_num = GPS_NUM;
4949 svid_idx = 0;
4950 if (!in.mSvHealth.empty()) {
4951 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
4952 eph_health_bad_mask = in.mSvHealth.back().mGpsBadMask;
4953 }
4954 if (!in.mXtra.empty()) {
4955 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
4956 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
4957 }
4958 break;
4959 case GNSS_SV_TYPE_GLONASS:
4960 svid_min = GNSS_BUGREPORT_GLO_MIN;
4961 svid_num = GLO_NUM;
4962 svid_idx = GPS_NUM;
4963 if (!in.mSvHealth.empty()) {
4964 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
4965 eph_health_bad_mask = in.mSvHealth.back().mGloBadMask;
4966 }
4967 if (!in.mXtra.empty()) {
4968 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
4969 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
4970 }
4971 break;
4972 case GNSS_SV_TYPE_QZSS:
4973 svid_min = GNSS_BUGREPORT_QZSS_MIN;
4974 svid_num = QZSS_NUM;
4975 svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
4976 if (!in.mSvHealth.empty()) {
4977 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
4978 eph_health_bad_mask = in.mSvHealth.back().mQzssBadMask;
4979 }
4980 if (!in.mXtra.empty()) {
4981 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
4982 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
4983 }
4984 break;
4985 case GNSS_SV_TYPE_BEIDOU:
4986 svid_min = GNSS_BUGREPORT_BDS_MIN;
4987 svid_num = BDS_NUM;
4988 svid_idx = GPS_NUM+GLO_NUM;
4989 if (!in.mSvHealth.empty()) {
4990 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
4991 eph_health_bad_mask = in.mSvHealth.back().mBdsBadMask;
4992 }
4993 if (!in.mXtra.empty()) {
4994 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
4995 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
4996 }
4997 break;
4998 case GNSS_SV_TYPE_GALILEO:
4999 svid_min = GNSS_BUGREPORT_GAL_MIN;
5000 svid_num = GAL_NUM;
5001 svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
5002 if (!in.mSvHealth.empty()) {
5003 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
5004 eph_health_bad_mask = in.mSvHealth.back().mGalBadMask;
5005 }
5006 if (!in.mXtra.empty()) {
5007 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
5008 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
5009 }
5010 break;
5011 case GNSS_SV_TYPE_NAVIC:
5012 svid_min = GNSS_BUGREPORT_NAVIC_MIN;
5013 svid_num = NAVIC_NUM;
5014 svid_idx = GPS_NUM+GLO_NUM+QZSS_NUM+BDS_NUM+GAL_NUM;
5015 if (!in.mSvHealth.empty()) {
5016 eph_health_good_mask = in.mSvHealth.back().mNavicGoodMask;
5017 eph_health_bad_mask = in.mSvHealth.back().mNavicBadMask;
5018 }
5019 if (!in.mXtra.empty()) {
5020 server_perdiction_available_mask = in.mXtra.back().mNavicXtraValid;
5021 server_perdiction_age = (float)(in.mXtra.back().mNavicXtraAge);
5022 }
5023 break;
5024 default:
5025 return;
5026 }
5027
5028 // extract each sv info from systemstatus report
5029 for(uint32_t i=0; i<svid_num && (svid_idx+i)<SV_ALL_NUM; i++) {
5030
5031 GnssDebugSatelliteInfo s = {};
5032 s.size = sizeof(s);
5033 s.svid = i + svid_min;
5034 s.constellation = in_constellation;
5035
5036 if (!in.mNavData.empty()) {
5037 s.mEphemerisType = in.mNavData.back().mNav[svid_idx+i].mType;
5038 s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
5039 }
5040 else {
5041 s.mEphemerisType = GNSS_EPH_TYPE_UNKNOWN;
5042 s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
5043 }
5044
5045 sv_mask = 0x1ULL << i;
5046 if (eph_health_good_mask & sv_mask) {
5047 s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
5048 }
5049 else if (eph_health_bad_mask & sv_mask) {
5050 s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
5051 }
5052 else {
5053 s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
5054 }
5055
5056 if (!in.mNavData.empty()) {
5057 s.ephemerisAgeSeconds =
5058 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
5059 }
5060 else {
5061 s.ephemerisAgeSeconds = 0.0f;
5062 }
5063
5064 if (server_perdiction_available_mask & sv_mask) {
5065 s.serverPredictionIsAvailable = true;
5066 }
5067 else {
5068 s.serverPredictionIsAvailable = false;
5069 }
5070
5071 s.serverPredictionAgeSeconds = server_perdiction_age;
5072 out.push_back(s);
5073 }
5074
5075 return;
5076 }
5077
getDebugReport(GnssDebugReport & r)5078 bool GnssAdapter::getDebugReport(GnssDebugReport& r)
5079 {
5080 LOC_LOGD("%s]: ", __func__);
5081
5082 SystemStatus* systemstatus = getSystemStatus();
5083 if (nullptr == systemstatus) {
5084 return false;
5085 }
5086
5087 SystemStatusReports reports = {};
5088 systemstatus->getReport(reports, true);
5089
5090 r.size = sizeof(r);
5091
5092 // location block
5093 r.mLocation.size = sizeof(r.mLocation);
5094 if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
5095 r.mLocation.mValid = true;
5096 r.mLocation.mLocation.latitude =
5097 reports.mLocation.back().mLocation.gpsLocation.latitude;
5098 r.mLocation.mLocation.longitude =
5099 reports.mLocation.back().mLocation.gpsLocation.longitude;
5100 r.mLocation.mLocation.altitude =
5101 reports.mLocation.back().mLocation.gpsLocation.altitude;
5102 r.mLocation.mLocation.speed =
5103 (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
5104 r.mLocation.mLocation.bearing =
5105 (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
5106 r.mLocation.mLocation.accuracy =
5107 (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
5108
5109 r.mLocation.verticalAccuracyMeters =
5110 reports.mLocation.back().mLocationEx.vert_unc;
5111 r.mLocation.speedAccuracyMetersPerSecond =
5112 reports.mLocation.back().mLocationEx.speed_unc;
5113 r.mLocation.bearingAccuracyDegrees =
5114 reports.mLocation.back().mLocationEx.bearing_unc;
5115
5116 r.mLocation.mUtcReported =
5117 reports.mLocation.back().mUtcReported;
5118 }
5119 else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
5120 r.mLocation.mValid = true;
5121 r.mLocation.mLocation.latitude =
5122 (double)(reports.mBestPosition.back().mBestLat) * RAD2DEG;
5123 r.mLocation.mLocation.longitude =
5124 (double)(reports.mBestPosition.back().mBestLon) * RAD2DEG;
5125 r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt;
5126 r.mLocation.mLocation.accuracy =
5127 (double)(reports.mBestPosition.back().mBestHepe);
5128
5129 r.mLocation.mUtcReported = reports.mBestPosition.back().mUtcReported;
5130 }
5131 else {
5132 r.mLocation.mValid = false;
5133 }
5134
5135 if (r.mLocation.mValid) {
5136 LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
5137 r.mLocation.mLocation.latitude,
5138 r.mLocation.mLocation.longitude,
5139 r.mLocation.mLocation.altitude,
5140 r.mLocation.mLocation.speed);
5141 }
5142
5143 // time block
5144 r.mTime.size = sizeof(r.mTime);
5145 if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
5146 r.mTime.mValid = true;
5147 r.mTime.timeEstimate =
5148 (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
5149 GNSS_UTC_TIME_OFFSET)*24*60*60 -
5150 (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
5151 (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
5152
5153 if (reports.mTimeAndClock.back().mTimeUncNs > 0) {
5154 // TimeUncNs value is available
5155 r.mTime.timeUncertaintyNs =
5156 (float)(reports.mTimeAndClock.back().mLeapSecUnc)*1000.0f +
5157 (float)(reports.mTimeAndClock.back().mTimeUncNs);
5158 } else {
5159 // fall back to legacy TimeUnc
5160 r.mTime.timeUncertaintyNs =
5161 ((float)(reports.mTimeAndClock.back().mTimeUnc) +
5162 (float)(reports.mTimeAndClock.back().mLeapSecUnc))*1000.0f;
5163 }
5164
5165 r.mTime.frequencyUncertaintyNsPerSec =
5166 (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
5167 LOC_LOGV("getDebugReport - timeestimate=%" PRIu64 " unc=%f frequnc=%f",
5168 r.mTime.timeEstimate,
5169 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
5170 }
5171 else {
5172 r.mTime.mValid = false;
5173 }
5174
5175 // satellite info block
5176 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
5177 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
5178 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
5179 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
5180 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
5181 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_NAVIC, reports);
5182 LOC_LOGV("getDebugReport - satellite=%zu", r.mSatelliteInfo.size());
5183
5184 return true;
5185 }
5186
5187 /* get AGC information from system status and fill it */
5188 void
getAgcInformation(GnssMeasurementsNotification & measurements,int msInWeek)5189 GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek)
5190 {
5191 SystemStatus* systemstatus = getSystemStatus();
5192
5193 if (nullptr != systemstatus) {
5194 SystemStatusReports reports = {};
5195 systemstatus->getReport(reports, true);
5196
5197 if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
5198 (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
5199
5200 for (size_t i = 0; i < measurements.count; i++) {
5201 switch (measurements.measurements[i].svType) {
5202 case GNSS_SV_TYPE_GPS:
5203 case GNSS_SV_TYPE_QZSS:
5204 measurements.measurements[i].agcLevelDb =
5205 (double)-reports.mRfAndParams.back().mJammerGps;
5206 measurements.measurements[i].flags |=
5207 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5208 break;
5209
5210 case GNSS_SV_TYPE_GALILEO:
5211 measurements.measurements[i].agcLevelDb =
5212 (double)-reports.mRfAndParams.back().mJammerGal;
5213 measurements.measurements[i].flags |=
5214 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5215 break;
5216
5217 case GNSS_SV_TYPE_GLONASS:
5218 measurements.measurements[i].agcLevelDb =
5219 (double)-reports.mRfAndParams.back().mJammerGlo;
5220 measurements.measurements[i].flags |=
5221 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5222 break;
5223
5224 case GNSS_SV_TYPE_BEIDOU:
5225 measurements.measurements[i].agcLevelDb =
5226 (double)-reports.mRfAndParams.back().mJammerBds;
5227 measurements.measurements[i].flags |=
5228 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5229 break;
5230
5231 case GNSS_SV_TYPE_SBAS:
5232 case GNSS_SV_TYPE_UNKNOWN:
5233 default:
5234 break;
5235 }
5236 }
5237 }
5238 }
5239 }
5240
5241 /* get Data information from system status and fill it */
5242 void
getDataInformation(GnssDataNotification & data,int msInWeek)5243 GnssAdapter::getDataInformation(GnssDataNotification& data, int msInWeek)
5244 {
5245 SystemStatus* systemstatus = getSystemStatus();
5246
5247 LOC_LOGV("%s]: msInWeek=%d", __func__, msInWeek);
5248 if (nullptr != systemstatus) {
5249 SystemStatusReports reports = {};
5250 systemstatus->getReport(reports, true);
5251
5252 if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
5253 (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
5254
5255 for (int sig = GNSS_LOC_SIGNAL_TYPE_GPS_L1CA;
5256 sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
5257 data.gnssDataMask[sig] = 0;
5258 data.jammerInd[sig] = 0.0;
5259 data.agc[sig] = 0.0;
5260 }
5261 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGps) {
5262 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
5263 GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5264 data.agc[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
5265 (double)-reports.mRfAndParams.back().mJammerGps;
5266 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
5267 (double)reports.mRfAndParams.back().mJammerGps;
5268 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
5269 GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5270 data.agc[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
5271 (double)-reports.mRfAndParams.back().mJammerGps;
5272 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
5273 (double)reports.mRfAndParams.back().mJammerGps;
5274 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
5275 GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5276 data.agc[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
5277 (double)-reports.mRfAndParams.back().mJammerGps;
5278 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
5279 (double)reports.mRfAndParams.back().mJammerGps;
5280 }
5281 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGlo) {
5282 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
5283 GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5284 data.agc[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
5285 (double)-reports.mRfAndParams.back().mJammerGlo;
5286 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
5287 (double)reports.mRfAndParams.back().mJammerGlo;
5288 }
5289 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerBds) {
5290 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
5291 GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5292 data.agc[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
5293 (double)-reports.mRfAndParams.back().mJammerBds;
5294 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
5295 (double)reports.mRfAndParams.back().mJammerBds;
5296 }
5297 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGal) {
5298 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
5299 GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5300 data.agc[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
5301 (double)-reports.mRfAndParams.back().mJammerGal;
5302 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
5303 (double)reports.mRfAndParams.back().mJammerGal;
5304 }
5305 }
5306 }
5307 }
5308
5309 /* Callbacks registered with loc_net_iface library */
agpsOpenResultCb(bool isSuccess,AGpsExtType agpsType,const char * apn,AGpsBearerType bearerType,void * userDataPtr)5310 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
5311 AGpsBearerType bearerType, void* userDataPtr) {
5312 LOC_LOGD("%s]: ", __func__);
5313 if (userDataPtr == nullptr) {
5314 LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
5315 return;
5316 }
5317 if (apn == nullptr) {
5318 LOC_LOGE("%s]: apn is nullptr.", __func__);
5319 return;
5320 }
5321 GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
5322 if (isSuccess) {
5323 adapter->dataConnOpenCommand(agpsType, apn, strlen(apn), bearerType);
5324 } else {
5325 adapter->dataConnFailedCommand(agpsType);
5326 }
5327 }
5328
agpsCloseResultCb(bool isSuccess,AGpsExtType agpsType,void * userDataPtr)5329 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr) {
5330 LOC_LOGD("%s]: ", __func__);
5331 if (userDataPtr == nullptr) {
5332 LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
5333 return;
5334 }
5335 GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
5336 if (isSuccess) {
5337 adapter->dataConnClosedCommand(agpsType);
5338 } else {
5339 adapter->dataConnFailedCommand(agpsType);
5340 }
5341 }
5342
5343 void
saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb)5344 GnssAdapter::saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb) {
5345 mGnssEnergyConsumedCb = energyConsumedCb;
5346 }
5347
5348 void
getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb)5349 GnssAdapter::getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb) {
5350 struct MsgGetGnssEnergyConsumed : public LocMsg {
5351 GnssAdapter& mAdapter;
5352 LocApiBase& mApi;
5353 GnssEnergyConsumedCallback mEnergyConsumedCb;
5354 inline MsgGetGnssEnergyConsumed(GnssAdapter& adapter, LocApiBase& api,
5355 GnssEnergyConsumedCallback energyConsumedCb) :
5356 LocMsg(),
5357 mAdapter(adapter),
5358 mApi(api),
5359 mEnergyConsumedCb(energyConsumedCb){}
5360 inline virtual void proc() const {
5361 mAdapter.saveGnssEnergyConsumedCallback(mEnergyConsumedCb);
5362 mApi.getGnssEnergyConsumed();
5363 }
5364 };
5365
5366 sendMsg(new MsgGetGnssEnergyConsumed(*this, *mLocApi, energyConsumedCb));
5367 }
5368
5369 void
nfwControlCommand(bool enable)5370 GnssAdapter::nfwControlCommand(bool enable) {
5371 struct MsgControlNfwLocationAccess : public LocMsg {
5372 GnssAdapter& mAdapter;
5373 LocApiBase& mApi;
5374 bool mEnable;
5375 inline MsgControlNfwLocationAccess(GnssAdapter& adapter, LocApiBase& api,
5376 bool enable) :
5377 LocMsg(),
5378 mAdapter(adapter),
5379 mApi(api),
5380 mEnable(enable) {}
5381 inline virtual void proc() const {
5382 GnssConfigGpsLock gpsLock;
5383
5384 gpsLock = ContextBase::mGps_conf.GPS_LOCK;
5385 if (mEnable) {
5386 gpsLock &= ~GNSS_CONFIG_GPS_LOCK_NI;
5387 } else {
5388 gpsLock |= GNSS_CONFIG_GPS_LOCK_NI;
5389 }
5390 ContextBase::mGps_conf.GPS_LOCK = gpsLock;
5391 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
5392 mApi.setGpsLockSync((GnssConfigGpsLock)gpsLock);
5393 }));
5394 }
5395 };
5396
5397 if (mSupportNfwControl) {
5398 sendMsg(new MsgControlNfwLocationAccess(*this, *mLocApi, enable));
5399 } else {
5400 LOC_LOGw("NFW control is not supported, do not use this for NFW");
5401 }
5402 }
5403
5404 // Set tunc constrained mode, use 0 session id to indicate
5405 // that no callback is needed. Session id 0 is used for calls that
5406 // are not invoked from the integration api, e.g.: initial configuration
5407 // from the configure file
5408 void
setConstrainedTunc(bool enable,float tuncConstraint,uint32_t energyBudget,uint32_t sessionId)5409 GnssAdapter::setConstrainedTunc(bool enable, float tuncConstraint,
5410 uint32_t energyBudget, uint32_t sessionId) {
5411
5412 mLocConfigInfo.tuncConfigInfo.isValid = true;
5413 mLocConfigInfo.tuncConfigInfo.enable = enable;
5414 mLocConfigInfo.tuncConfigInfo.tuncThresholdMs = tuncConstraint;
5415 mLocConfigInfo.tuncConfigInfo.energyBudget = energyBudget;
5416
5417 LocApiResponse* locApiResponse = nullptr;
5418 if (sessionId != 0) {
5419 locApiResponse =
5420 new LocApiResponse(*getContext(),
5421 [this, sessionId] (LocationError err) {
5422 reportResponse(err, sessionId);});
5423 if (!locApiResponse) {
5424 LOC_LOGe("memory alloc failed");
5425 }
5426 }
5427 mLocApi->setConstrainedTuncMode(
5428 enable, tuncConstraint, energyBudget, locApiResponse);
5429 }
5430
5431 uint32_t
setConstrainedTuncCommand(bool enable,float tuncConstraint,uint32_t energyBudget)5432 GnssAdapter::setConstrainedTuncCommand (bool enable, float tuncConstraint,
5433 uint32_t energyBudget) {
5434 // generated session id will be none-zero
5435 uint32_t sessionId = generateSessionId();
5436 LOC_LOGd("session id %u", sessionId);
5437
5438 struct MsgEnableTUNC : public LocMsg {
5439 GnssAdapter& mAdapter;
5440 uint32_t mSessionId;
5441 bool mEnable;
5442 float mTuncConstraint;
5443 uint32_t mEnergyBudget;
5444
5445 inline MsgEnableTUNC(GnssAdapter& adapter,
5446 uint32_t sessionId,
5447 bool enable,
5448 float tuncConstraint,
5449 uint32_t energyBudget) :
5450 LocMsg(),
5451 mAdapter(adapter),
5452 mSessionId(sessionId),
5453 mEnable(enable),
5454 mTuncConstraint(tuncConstraint),
5455 mEnergyBudget(energyBudget) {}
5456 inline virtual void proc() const {
5457 mAdapter.setConstrainedTunc(mEnable, mTuncConstraint,
5458 mEnergyBudget, mSessionId);
5459 }
5460 };
5461
5462 sendMsg(new MsgEnableTUNC(*this, sessionId, enable,
5463 tuncConstraint, energyBudget));
5464
5465 return sessionId;
5466 }
5467
5468 // Set position assisted clock estimator, use 0 session id to indicate
5469 // that no callback is needed. Session id 0 is used for calls that are
5470 // not invoked from the integration api, e.g.: initial configuration
5471 // from the configure file.
5472 void
setPositionAssistedClockEstimator(bool enable,uint32_t sessionId)5473 GnssAdapter::setPositionAssistedClockEstimator(bool enable,
5474 uint32_t sessionId) {
5475
5476 mLocConfigInfo.paceConfigInfo.isValid = true;
5477 mLocConfigInfo.paceConfigInfo.enable = enable;
5478 LocApiResponse* locApiResponse = nullptr;
5479 if (sessionId != 0) {
5480 locApiResponse =
5481 new LocApiResponse(*getContext(),
5482 [this, sessionId] (LocationError err) {
5483 reportResponse(err, sessionId);});
5484 if (!locApiResponse) {
5485 LOC_LOGe("memory alloc failed");
5486 }
5487 }
5488 mLocApi->setPositionAssistedClockEstimatorMode(enable, locApiResponse);
5489 }
5490
5491 uint32_t
setPositionAssistedClockEstimatorCommand(bool enable)5492 GnssAdapter::setPositionAssistedClockEstimatorCommand(bool enable) {
5493 // generated session id will be none-zero
5494 uint32_t sessionId = generateSessionId();
5495 LOC_LOGd("session id %u", sessionId);
5496
5497 struct MsgEnablePACE : public LocMsg {
5498 GnssAdapter& mAdapter;
5499 uint32_t mSessionId;
5500 bool mEnable;
5501 inline MsgEnablePACE(GnssAdapter& adapter,
5502 uint32_t sessionId, bool enable) :
5503 LocMsg(),
5504 mAdapter(adapter),
5505 mSessionId(sessionId),
5506 mEnable(enable){}
5507 inline virtual void proc() const {
5508 mAdapter.setPositionAssistedClockEstimator(mEnable, mSessionId);
5509 }
5510 };
5511
5512 sendMsg(new MsgEnablePACE(*this, sessionId, enable));
5513 return sessionId;
5514 }
5515
5516 void
updateSvConfig(uint32_t sessionId,const GnssSvTypeConfig & svTypeConfig,const GnssSvIdConfig & svIdConfig)5517 GnssAdapter::updateSvConfig(uint32_t sessionId,
5518 const GnssSvTypeConfig& svTypeConfig,
5519 const GnssSvIdConfig& svIdConfig) {
5520
5521 // check whether if any constellation is removed from the new config
5522 GnssSvTypesMask enabledRemoved = mGnssSvTypeConfig.enabledSvTypesMask &
5523 (mGnssSvTypeConfig.enabledSvTypesMask ^ svTypeConfig.enabledSvTypesMask);
5524 // Send reset if any constellation is removed from the enabled list
5525 if (enabledRemoved != 0) {
5526 mLocApi->resetConstellationControl();
5527 }
5528
5529 mGnssSvTypeConfig = svTypeConfig;
5530 mGnssSvIdConfig = svIdConfig;
5531 mBlacklistedSvIds.clear();
5532 convertFromGnssSvIdConfig(svIdConfig, mBlacklistedSvIds);
5533
5534 // Send blacklist info
5535 mLocApi->setBlacklistSv(mGnssSvIdConfig);
5536
5537 // Send only enabled constellation config
5538 GnssSvTypeConfig svTypeConfigCopy = {sizeof(GnssSvTypeConfig), 0, 0};
5539 svTypeConfigCopy.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask;
5540 LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
5541 [this, sessionId] (LocationError err) {
5542 reportResponse(err, sessionId);});
5543 if (!locApiResponse) {
5544 LOC_LOGe("memory alloc failed");
5545 }
5546 mLocApi->setConstellationControl(svTypeConfigCopy, locApiResponse);
5547 }
5548
gnssUpdateSvConfigCommand(const GnssSvTypeConfig & svTypeConfig,const GnssSvIdConfig & svIdConfig)5549 uint32_t GnssAdapter::gnssUpdateSvConfigCommand(
5550 const GnssSvTypeConfig& svTypeConfig,
5551 const GnssSvIdConfig& svIdConfig) {
5552
5553 // generated session id will be none-zero
5554 uint32_t sessionId = generateSessionId();
5555 LOC_LOGd("session id %u", sessionId);
5556
5557 struct MsgUpdateSvConfig : public LocMsg {
5558 GnssAdapter& mAdapter;
5559 uint32_t mSessionId;
5560 GnssSvTypeConfig mSvTypeConfig;
5561 GnssSvIdConfig mSvIdConfig;
5562
5563 inline MsgUpdateSvConfig(GnssAdapter& adapter,
5564 uint32_t sessionId,
5565 const GnssSvTypeConfig& svTypeConfig,
5566 const GnssSvIdConfig& svIdConfig) :
5567 LocMsg(),
5568 mAdapter(adapter),
5569 mSessionId(sessionId),
5570 mSvTypeConfig(svTypeConfig),
5571 mSvIdConfig(svIdConfig) {}
5572 inline virtual void proc() const {
5573 mAdapter.updateSvConfig(mSessionId, mSvTypeConfig, mSvIdConfig);
5574 }
5575 };
5576
5577 if (sessionId != 0) {
5578 sendMsg(new MsgUpdateSvConfig(*this, sessionId,
5579 svTypeConfig, svIdConfig));
5580 }
5581 return sessionId;
5582 }
5583
5584 void
resetSvConfig(uint32_t sessionId)5585 GnssAdapter::resetSvConfig(uint32_t sessionId) {
5586
5587 // Clear blacklisting
5588 memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
5589 mGnssSvIdConfig.size = sizeof(mGnssSvIdConfig);
5590 mBlacklistedSvIds.clear();
5591 gnssSvIdConfigUpdate();
5592
5593 // Reset constellation config, including mGnssSvTypeConfig
5594 // when size is set to 0, upon subsequent modem restart, sv type
5595 // config will not be sent down to modem
5596 gnssSetSvTypeConfig({sizeof(GnssSvTypeConfig), 0, 0});
5597
5598 LocApiResponse* locApiResponse = nullptr;
5599 if (sessionId != 0) {
5600 locApiResponse =
5601 new LocApiResponse(*getContext(),
5602 [this, sessionId] (LocationError err) {
5603 reportResponse(err, sessionId);});
5604 if (!locApiResponse) {
5605 LOC_LOGe("memory alloc failed");
5606 }
5607 }
5608 mLocApi->resetConstellationControl(locApiResponse);
5609 }
5610
gnssResetSvConfigCommand()5611 uint32_t GnssAdapter::gnssResetSvConfigCommand() {
5612
5613 // generated session id will be none-zero
5614 uint32_t sessionId = generateSessionId();
5615 LOC_LOGd("session id %u", sessionId);
5616
5617 struct MsgResetSvConfig : public LocMsg {
5618 GnssAdapter& mAdapter;
5619 uint32_t mSessionId;
5620
5621 inline MsgResetSvConfig(GnssAdapter& adapter,
5622 uint32_t sessionId) :
5623 LocMsg(),
5624 mAdapter(adapter),
5625 mSessionId(sessionId) {}
5626 inline virtual void proc() const {
5627 mAdapter.resetSvConfig(mSessionId);
5628 }
5629 };
5630
5631 sendMsg(new MsgResetSvConfig(*this, sessionId));
5632 return sessionId;
5633 }
5634
5635 void
configLeverArm(uint32_t sessionId,const LeverArmConfigInfo & configInfo)5636 GnssAdapter::configLeverArm(uint32_t sessionId,
5637 const LeverArmConfigInfo& configInfo) {
5638
5639 LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
5640 if (true == mEngHubProxy->configLeverArm(configInfo)) {
5641 err = LOCATION_ERROR_SUCCESS;
5642 }
5643 reportResponse(err, sessionId);
5644 }
5645
5646 uint32_t
configLeverArmCommand(const LeverArmConfigInfo & configInfo)5647 GnssAdapter::configLeverArmCommand(const LeverArmConfigInfo& configInfo) {
5648
5649 // generated session id will be none-zero
5650 uint32_t sessionId = generateSessionId();
5651 LOC_LOGd("session id %u", sessionId);
5652
5653 struct MsgConfigLeverArm : public LocMsg {
5654 GnssAdapter& mAdapter;
5655 uint32_t mSessionId;
5656 LeverArmConfigInfo mConfigInfo;
5657
5658 inline MsgConfigLeverArm(GnssAdapter& adapter,
5659 uint32_t sessionId,
5660 const LeverArmConfigInfo& configInfo) :
5661 LocMsg(),
5662 mAdapter(adapter),
5663 mSessionId(sessionId),
5664 mConfigInfo(configInfo) {}
5665 inline virtual void proc() const {
5666 mAdapter.configLeverArm(mSessionId, mConfigInfo);
5667 }
5668 };
5669
5670 sendMsg(new MsgConfigLeverArm(*this, sessionId, configInfo));
5671 return sessionId;
5672 }
5673
initMeasCorr(bool bSendCbWhenNotSupported)5674 bool GnssAdapter::initMeasCorr(bool bSendCbWhenNotSupported) {
5675 LOC_LOGv("GnssAdapter::initMeasCorr");
5676 /* Message to initialize Measurement Corrections */
5677 struct MsgInitMeasCorr : public LocMsg {
5678 GnssAdapter& mAdapter;
5679 GnssMeasurementCorrectionsCapabilitiesMask mCapMask;
5680
5681 inline MsgInitMeasCorr(GnssAdapter& adapter,
5682 GnssMeasurementCorrectionsCapabilitiesMask capMask) :
5683 LocMsg(), mAdapter(adapter), mCapMask(capMask) {
5684 LOC_LOGv("MsgInitMeasCorr");
5685 }
5686
5687 inline virtual void proc() const {
5688 LOC_LOGv("MsgInitMeasCorr::proc()");
5689
5690 mAdapter.mMeasCorrSetCapabilitiesCb(mCapMask);
5691 }
5692 };
5693 if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
5694 sendMsg(new MsgInitMeasCorr(*this, GNSS_MEAS_CORR_LOS_SATS |
5695 GNSS_MEAS_CORR_EXCESS_PATH_LENGTH | GNSS_MEAS_CORR_REFLECTING_PLANE));
5696 return true;
5697 } else {
5698 LOC_LOGv("MEASUREMENTS_CORRECTION feature is not supported in the modem");
5699 if (bSendCbWhenNotSupported) {
5700 sendMsg(new MsgInitMeasCorr(*this, 0));
5701 }
5702 return false;
5703 }
5704 }
5705
openMeasCorrCommand(const measCorrSetCapabilitiesCb setCapabilitiesCb)5706 bool GnssAdapter::openMeasCorrCommand(const measCorrSetCapabilitiesCb setCapabilitiesCb) {
5707 LOC_LOGi("GnssAdapter::openMeasCorrCommand");
5708
5709 /* Send message to initialize Measurement Corrections */
5710 mMeasCorrSetCapabilitiesCb = setCapabilitiesCb;
5711 mIsMeasCorrInterfaceOpen = true;
5712 if (isEngineCapabilitiesKnown()) {
5713 LOC_LOGv("Capabilities are known, proceed with measurement corrections init");
5714 return initMeasCorr(false);
5715 } else {
5716 LOC_LOGv("Capabilities are not known, wait for open");
5717 return true;
5718 }
5719 }
5720
measCorrSetCorrectionsCommand(const GnssMeasurementCorrections gnssMeasCorr)5721 bool GnssAdapter::measCorrSetCorrectionsCommand(const GnssMeasurementCorrections gnssMeasCorr) {
5722 LOC_LOGi("GnssAdapter::measCorrSetCorrectionsCommand");
5723
5724 /* Message to set Measurement Corrections */
5725 struct MsgSetCorrectionsMeasCorr : public LocMsg {
5726 const GnssMeasurementCorrections mGnssMeasCorr;
5727 GnssAdapter& mAdapter;
5728 LocApiBase& mApi;
5729
5730 inline MsgSetCorrectionsMeasCorr(
5731 const GnssMeasurementCorrections gnssMeasCorr,
5732 GnssAdapter& adapter,
5733 LocApiBase& api) :
5734 LocMsg(),
5735 mGnssMeasCorr(gnssMeasCorr),
5736 mAdapter(adapter),
5737 mApi(api) {
5738 LOC_LOGv("MsgSetCorrectionsMeasCorr");
5739 }
5740
5741 inline virtual void proc() const {
5742 LOC_LOGv("MsgSetCorrectionsMeasCorr::proc()");
5743 mApi.setMeasurementCorrections(mGnssMeasCorr);
5744 }
5745 };
5746
5747 if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
5748 sendMsg(new MsgSetCorrectionsMeasCorr(gnssMeasCorr, *this, *mLocApi));
5749 return true;
5750 } else {
5751 LOC_LOGw("Measurement Corrections are not supported!");
5752 return false;
5753 }
5754 }
antennaInfoInitCommand(const antennaInfoCb antennaInfoCallback)5755 uint32_t GnssAdapter::antennaInfoInitCommand(const antennaInfoCb antennaInfoCallback) {
5756 LOC_LOGi("GnssAdapter::antennaInfoInitCommand");
5757
5758 /* Message to initialize Antenna Information */
5759 struct MsgInitAi : public LocMsg {
5760 const antennaInfoCb mAntennaInfoCb;
5761 GnssAdapter& mAdapter;
5762
5763 inline MsgInitAi(const antennaInfoCb antennaInfoCallback, GnssAdapter& adapter) :
5764 LocMsg(), mAntennaInfoCb(antennaInfoCallback), mAdapter(adapter) {
5765 LOC_LOGv("MsgInitAi");
5766 }
5767
5768 inline virtual void proc() const {
5769 LOC_LOGv("MsgInitAi::proc()");
5770 mAdapter.reportGnssAntennaInformation(mAntennaInfoCb);
5771 }
5772 };
5773 if (mIsAntennaInfoInterfaceOpened) {
5774 return ANTENNA_INFO_ERROR_ALREADY_INIT;
5775 } else {
5776 mIsAntennaInfoInterfaceOpened = true;
5777 sendMsg(new MsgInitAi(antennaInfoCallback, *this));
5778 return ANTENNA_INFO_SUCCESS;
5779 }
5780 }
5781
5782 void
configRobustLocation(uint32_t sessionId,bool enable,bool enableForE911)5783 GnssAdapter::configRobustLocation(uint32_t sessionId,
5784 bool enable, bool enableForE911) {
5785
5786 mLocConfigInfo.robustLocationConfigInfo.isValid = true;
5787 mLocConfigInfo.robustLocationConfigInfo.enable = enable;
5788 mLocConfigInfo.robustLocationConfigInfo.enableFor911 = enableForE911;
5789
5790 LocApiResponse* locApiResponse = nullptr;
5791 if (sessionId != 0) {
5792 locApiResponse =
5793 new LocApiResponse(*getContext(),
5794 [this, sessionId] (LocationError err) {
5795 reportResponse(err, sessionId);});
5796 if (!locApiResponse) {
5797 LOC_LOGe("memory alloc failed");
5798 }
5799 }
5800 mLocApi->configRobustLocation(enable, enableForE911, locApiResponse);
5801 }
5802
configRobustLocationCommand(bool enable,bool enableForE911)5803 uint32_t GnssAdapter::configRobustLocationCommand(
5804 bool enable, bool enableForE911) {
5805
5806 // generated session id will be none-zero
5807 uint32_t sessionId = generateSessionId();
5808 LOC_LOGd("session id %u", sessionId);
5809
5810 struct MsgConfigRobustLocation : public LocMsg {
5811 GnssAdapter& mAdapter;
5812 uint32_t mSessionId;
5813 bool mEnable;
5814 bool mEnableForE911;
5815
5816 inline MsgConfigRobustLocation(GnssAdapter& adapter,
5817 uint32_t sessionId,
5818 bool enable,
5819 bool enableForE911) :
5820 LocMsg(),
5821 mAdapter(adapter),
5822 mSessionId(sessionId),
5823 mEnable(enable),
5824 mEnableForE911(enableForE911) {}
5825 inline virtual void proc() const {
5826 mAdapter.configRobustLocation(mSessionId, mEnable, mEnableForE911);
5827 }
5828 };
5829
5830 sendMsg(new MsgConfigRobustLocation(*this, sessionId, enable, enableForE911));
5831 return sessionId;
5832 }
5833
5834 void
configMinGpsWeek(uint32_t sessionId,uint16_t minGpsWeek)5835 GnssAdapter::configMinGpsWeek(uint32_t sessionId, uint16_t minGpsWeek) {
5836 // suspend all sessions for modem to take the min GPS week config
5837 suspendSessions();
5838
5839 LocApiResponse* locApiResponse = nullptr;
5840 if (sessionId != 0) {
5841 locApiResponse =
5842 new LocApiResponse(*getContext(),
5843 [this, sessionId] (LocationError err) {
5844 reportResponse(err, sessionId);});
5845 if (!locApiResponse) {
5846 LOC_LOGe("memory alloc failed");
5847 }
5848 }
5849 mLocApi->configMinGpsWeek(minGpsWeek, locApiResponse);
5850
5851 // resume all tracking sessions after the min GPS week config
5852 // has been changed
5853 restartSessions(false);
5854 }
5855
configMinGpsWeekCommand(uint16_t minGpsWeek)5856 uint32_t GnssAdapter::configMinGpsWeekCommand(uint16_t minGpsWeek) {
5857 // generated session id will be none-zero
5858 uint32_t sessionId = generateSessionId();
5859 LOC_LOGd("session id %u", sessionId);
5860
5861 struct MsgConfigMinGpsWeek : public LocMsg {
5862 GnssAdapter& mAdapter;
5863 uint32_t mSessionId;
5864 uint16_t mMinGpsWeek;
5865
5866 inline MsgConfigMinGpsWeek(GnssAdapter& adapter,
5867 uint32_t sessionId,
5868 uint16_t minGpsWeek) :
5869 LocMsg(),
5870 mAdapter(adapter),
5871 mSessionId(sessionId),
5872 mMinGpsWeek(minGpsWeek) {}
5873 inline virtual void proc() const {
5874 mAdapter.configMinGpsWeek(mSessionId, mMinGpsWeek);
5875 }
5876 };
5877
5878 sendMsg(new MsgConfigMinGpsWeek(*this, sessionId, minGpsWeek));
5879 return sessionId;
5880 }
5881
configBodyToSensorMountParamsCommand(const BodyToSensorMountParams & b2sParams)5882 uint32_t GnssAdapter::configBodyToSensorMountParamsCommand(
5883 const BodyToSensorMountParams& b2sParams) {
5884
5885 // generated session id will be none-zero
5886 uint32_t sessionId = generateSessionId();
5887 LOC_LOGd("session id %u", sessionId);
5888
5889 struct MsgConfigB2sParams : public LocMsg {
5890 GnssAdapter& mAdapter;
5891 uint32_t mSessionId;
5892 BodyToSensorMountParams mB2sParams;
5893
5894 inline MsgConfigB2sParams(GnssAdapter& adapter,
5895 uint32_t sessionId,
5896 const BodyToSensorMountParams& b2sParams) :
5897 LocMsg(),
5898 mAdapter(adapter),
5899 mSessionId(sessionId),
5900 mB2sParams(b2sParams) {}
5901 inline virtual void proc() const {
5902 LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
5903 if (true == mAdapter.mEngHubProxy->configBodyToSensorMountParams(mB2sParams)) {
5904 err = LOCATION_ERROR_SUCCESS;
5905 }
5906 mAdapter.reportResponse(err, mSessionId);
5907 }
5908 };
5909
5910 sendMsg(new MsgConfigB2sParams(*this, sessionId, b2sParams));
5911 return sessionId;
5912 }
5913
reportGnssConfigEvent(uint32_t sessionId,const GnssConfig & gnssConfig)5914 void GnssAdapter::reportGnssConfigEvent(uint32_t sessionId, const GnssConfig& gnssConfig)
5915 {
5916 struct MsgReportGnssConfig : public LocMsg {
5917 GnssAdapter& mAdapter;
5918 uint32_t mSessionId;
5919 mutable GnssConfig mGnssConfig;
5920 inline MsgReportGnssConfig(GnssAdapter& adapter,
5921 uint32_t sessionId,
5922 const GnssConfig& gnssConfig) :
5923 LocMsg(),
5924 mAdapter(adapter),
5925 mSessionId(sessionId),
5926 mGnssConfig(gnssConfig) {}
5927 inline virtual void proc() const {
5928 // Invoke control clients config callback
5929 if (nullptr != mAdapter.mControlCallbacks.gnssConfigCb) {
5930 mAdapter.mControlCallbacks.gnssConfigCb(mSessionId, mGnssConfig);
5931 } else {
5932 LOC_LOGe("Failed to report, callback not registered");
5933 }
5934 }
5935 };
5936
5937 sendMsg(new MsgReportGnssConfig(*this, sessionId, gnssConfig));
5938 }
5939
5940 /* ==== Eng Hub Proxy ================================================================= */
5941 /* ======== UTILITIES ================================================================= */
5942 void
initEngHubProxyCommand()5943 GnssAdapter::initEngHubProxyCommand() {
5944 LOC_LOGD("%s]: ", __func__);
5945
5946 struct MsgInitEngHubProxy : public LocMsg {
5947 GnssAdapter* mAdapter;
5948 inline MsgInitEngHubProxy(GnssAdapter* adapter) :
5949 LocMsg(),
5950 mAdapter(adapter) {}
5951 inline virtual void proc() const {
5952 mAdapter->initEngHubProxy();
5953 }
5954 };
5955
5956 sendMsg(new MsgInitEngHubProxy(this));
5957 }
5958
5959 bool
initEngHubProxy()5960 GnssAdapter::initEngHubProxy() {
5961 static bool firstTime = true;
5962 static bool engHubLoadSuccessful = false;
5963
5964 const char *error = nullptr;
5965 unsigned int processListLength = 0;
5966 loc_process_info_s_type* processInfoList = nullptr;
5967
5968 do {
5969 // load eng hub only once
5970 if (firstTime == false) {
5971 break;
5972 }
5973
5974 int rc = loc_read_process_conf(LOC_PATH_IZAT_CONF, &processListLength,
5975 &processInfoList);
5976 if (rc != 0) {
5977 LOC_LOGE("%s]: failed to parse conf file", __func__);
5978 break;
5979 }
5980
5981 bool pluginDaemonEnabled = false;
5982 // go over the conf table to see whether any plugin daemon is enabled
5983 for (unsigned int i = 0; i < processListLength; i++) {
5984 if ((strncmp(processInfoList[i].name[0], PROCESS_NAME_ENGINE_SERVICE,
5985 strlen(PROCESS_NAME_ENGINE_SERVICE)) == 0) &&
5986 (processInfoList[i].proc_status == ENABLED)) {
5987 pluginDaemonEnabled = true;
5988 break;
5989 }
5990 }
5991
5992 // no plugin daemon is enabled for this platform, no need to load eng hub .so
5993 if (pluginDaemonEnabled == false) {
5994 break;
5995 }
5996
5997 // load the engine hub .so, if the .so is not present
5998 // all EngHubProxyBase calls will turn into no-op.
5999 void *handle = nullptr;
6000 if ((handle = dlopen("libloc_eng_hub.so", RTLD_NOW)) == nullptr) {
6001 if ((error = dlerror()) != nullptr) {
6002 LOC_LOGE("%s]: libloc_eng_hub.so not found %s !", __func__, error);
6003 }
6004 break;
6005 }
6006
6007 // prepare the callback functions
6008 // callback function for engine hub to report back position event
6009 GnssAdapterReportEnginePositionsEventCb reportPositionEventCb =
6010 [this](int count, EngineLocationInfo* locationArr) {
6011 // report from engine hub on behalf of PPE will be treated as fromUlp
6012 reportEnginePositionsEvent(count, locationArr);
6013 };
6014
6015 // callback function for engine hub to report back sv event
6016 GnssAdapterReportSvEventCb reportSvEventCb =
6017 [this](const GnssSvNotification& svNotify, bool fromEngineHub) {
6018 reportSvEvent(svNotify, fromEngineHub);
6019 };
6020
6021 // callback function for engine hub to request for complete aiding data
6022 GnssAdapterReqAidingDataCb reqAidingDataCb =
6023 [this] (const GnssAidingDataSvMask& svDataMask) {
6024 mLocApi->requestForAidingData(svDataMask);
6025 };
6026
6027 GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb =
6028 [this] (bool nHzNeeded, bool nHzMeasNeeded) {
6029
6030 if (nHzMeasNeeded &&
6031 (!checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT))) {
6032 updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT,
6033 LOC_REGISTRATION_MASK_ENABLED);
6034 } else if (checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT)) {
6035 updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT,
6036 LOC_REGISTRATION_MASK_DISABLED);
6037 }
6038
6039 if (mNHzNeeded != nHzNeeded) {
6040 mNHzNeeded = nHzNeeded;
6041 checkAndRestartSPESession();
6042 }
6043 };
6044
6045 getEngHubProxyFn* getter = (getEngHubProxyFn*) dlsym(handle, "getEngHubProxy");
6046 if(getter != nullptr) {
6047 EngineHubProxyBase* hubProxy = (*getter) (mMsgTask, mSystemStatus->getOsObserver(),
6048 reportPositionEventCb,
6049 reportSvEventCb, reqAidingDataCb,
6050 updateNHzRequirementCb);
6051 if (hubProxy != nullptr) {
6052 mEngHubProxy = hubProxy;
6053 engHubLoadSuccessful = true;
6054 }
6055 }
6056 else {
6057 LOC_LOGD("%s]: entered, did not find function", __func__);
6058 }
6059
6060 LOC_LOGD("%s]: first time initialization %d, returned %d",
6061 __func__, firstTime, engHubLoadSuccessful);
6062
6063 } while (0);
6064
6065 if (processInfoList != nullptr) {
6066 free (processInfoList);
6067 processInfoList = nullptr;
6068 }
6069
6070 firstTime = false;
6071 return engHubLoadSuccessful;
6072 }
6073
6074 std::vector<double>
parseDoublesString(char * dString)6075 GnssAdapter::parseDoublesString(char* dString) {
6076 std::vector<double> dVector;
6077 char* tmp = NULL;
6078 char* substr;
6079
6080 dVector.clear();
6081 for (substr = strtok_r(dString, " ", &tmp);
6082 substr != NULL;
6083 substr = strtok_r(NULL, " ", &tmp)) {
6084 dVector.push_back(std::stod(substr));
6085 }
6086 return dVector;
6087 }
6088
6089 void
reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallback)6090 GnssAdapter::reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallback)
6091 {
6092 #define MAX_TEXT_WIDTH 50
6093 #define MAX_COLUMN_WIDTH 20
6094
6095 /* parse antenna_corrections file and fill in
6096 a vector of GnssAntennaInformation data structure */
6097
6098 std::vector<GnssAntennaInformation> gnssAntennaInformations;
6099 GnssAntennaInformation gnssAntennaInfo;
6100
6101 uint32_t antennaInfoVectorSize;
6102 loc_param_s_type ant_info_vector_table[] =
6103 {
6104 { "ANTENNA_INFO_VECTOR_SIZE", &antennaInfoVectorSize, NULL, 'n' }
6105 };
6106 UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_info_vector_table);
6107
6108 for (uint32_t i = 0; i < antennaInfoVectorSize; i++) {
6109 double carrierFrequencyMHz;
6110 char pcOffsetStr[LOC_MAX_PARAM_STRING];
6111 uint32_t numberOfRows = 0;
6112 uint32_t numberOfColumns = 0;
6113 uint32_t numberOfRowsSGC = 0;
6114 uint32_t numberOfColumnsSGC = 0;
6115
6116 gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.clear();
6117 gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.clear();
6118 gnssAntennaInfo.signalGainCorrectionDbi.clear();
6119 gnssAntennaInfo.signalGainCorrectionUncertaintyDbi.clear();
6120 string s1 = "CARRIER_FREQUENCY_";
6121 s1 += to_string(i);
6122 string s2 = "PC_OFFSET_";
6123 s2 += to_string(i);
6124 string s3 = "NUMBER_OF_ROWS_";
6125 s3 += to_string(i);
6126 string s4 = "NUMBER_OF_COLUMNS_";
6127 s4 += to_string(i);
6128 string s5 = "NUMBER_OF_ROWS_SGC_";
6129 s5 += to_string(i);
6130 string s6 = "NUMBER_OF_COLUMNS_SGC_";
6131 s6 += to_string(i);
6132
6133 gnssAntennaInfo.size = sizeof(gnssAntennaInfo);
6134 loc_param_s_type ant_cf_table[] =
6135 {
6136 { s1.c_str(), &carrierFrequencyMHz, NULL, 'f' },
6137 { s2.c_str(), &pcOffsetStr, NULL, 's' },
6138 { s3.c_str(), &numberOfRows, NULL, 'n' },
6139 { s4.c_str(), &numberOfColumns, NULL, 'n' },
6140 { s5.c_str(), &numberOfRowsSGC, NULL, 'n' },
6141 { s6.c_str(), &numberOfColumnsSGC, NULL, 'n' },
6142 };
6143 UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_cf_table);
6144
6145 if (0 == numberOfRowsSGC) {
6146 numberOfRowsSGC = numberOfRows;
6147 }
6148 if (0 == numberOfColumnsSGC) {
6149 numberOfColumnsSGC = numberOfColumns;
6150 }
6151
6152 gnssAntennaInfo.carrierFrequencyMHz = carrierFrequencyMHz;
6153
6154 // now parse pcOffsetStr to get each entry
6155 std::vector<double> pcOffset;
6156 pcOffset = parseDoublesString(pcOffsetStr);
6157 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.size =
6158 sizeof(gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters);
6159 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.x = pcOffset[0];
6160 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.xUncertainty = pcOffset[1];
6161 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.y = pcOffset[2];
6162 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.yUncertainty = pcOffset[3];
6163 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.z = pcOffset[4];
6164 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.zUncertainty = pcOffset[5];
6165
6166 uint16_t array_size = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumns;
6167 uint16_t array_size_SGC = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumnsSGC;
6168 for (uint32_t j = 0; j < numberOfRows; j++) {
6169 char pcVarCorrStr[array_size];
6170 char pcVarCorrUncStr[array_size];
6171
6172 string s1 = "PC_VARIATION_CORRECTION_" + to_string(i) + "_ROW_";
6173 s1 += to_string(j);
6174 string s2 = "PC_VARIATION_CORRECTION_UNC_" + to_string(i) + "_ROW_";
6175 s2 += to_string(j);
6176
6177 loc_param_s_type ant_row_table[] =
6178 {
6179 { s1.c_str(), &pcVarCorrStr, NULL, 's' },
6180 { s2.c_str(), &pcVarCorrUncStr, NULL, 's' },
6181 };
6182 UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size);
6183
6184 gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.push_back(
6185 parseDoublesString(pcVarCorrStr));
6186 gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.push_back(
6187 parseDoublesString(pcVarCorrUncStr));
6188 }
6189 for (uint32_t j = 0; j < numberOfRowsSGC; j++) {
6190 char sigGainCorrStr[array_size_SGC];
6191 char sigGainCorrUncStr[array_size_SGC];
6192
6193 string s3 = "SIGNAL_GAIN_CORRECTION_" + to_string(i) + "_ROW_";
6194 s3 += to_string(j);
6195 string s4 = "SIGNAL_GAIN_CORRECTION_UNC_" + to_string(i) + "_ROW_";
6196 s4 += to_string(j);
6197
6198 loc_param_s_type ant_row_table[] =
6199 {
6200 { s3.c_str(), &sigGainCorrStr, NULL, 's' },
6201 { s4.c_str(), &sigGainCorrUncStr, NULL, 's' },
6202 };
6203 UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size_SGC);
6204
6205 gnssAntennaInfo.signalGainCorrectionDbi.push_back(
6206 parseDoublesString(sigGainCorrStr));
6207 gnssAntennaInfo.signalGainCorrectionUncertaintyDbi.push_back(
6208 parseDoublesString(sigGainCorrUncStr));
6209 }
6210 gnssAntennaInformations.push_back(std::move(gnssAntennaInfo));
6211 }
6212 if (antennaInfoVectorSize > 0)
6213 antennaInfoCallback(gnssAntennaInformations);
6214 }
6215
6216 /* ==== DGnss Usable Reporter ========================================================= */
6217 /* ======== UTILITIES ================================================================= */
6218
initDGnssUsableReporter()6219 void GnssAdapter::initDGnssUsableReporter()
6220 {
6221 if (nullptr == mCdfwInterface) {
6222 void* libHandle = nullptr;
6223 getCdfwInterface getter = (getCdfwInterface)dlGetSymFromLib(libHandle,
6224 "libcdfw.so", "getQCdfwInterface");
6225 if (nullptr == getter) {
6226 LOC_LOGe("dlGetSymFromLib getQCdfwInterface failed");
6227 } else {
6228 mCdfwInterface = getter();
6229 }
6230 }
6231 if (nullptr != mCdfwInterface) {
6232 QDgnssSessionActiveCb qDgnssSessionActiveCb = [this] (bool sessionActive) {
6233 mDGnssNeedReport = sessionActive;
6234 };
6235 mQDgnssListenerHDL = mCdfwInterface->createUsableReporter(qDgnssSessionActiveCb);
6236 }
6237 }
6238